From c7dec3762b2bc85be3973adbdca586322af4dba5 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 16 Aug 2023 20:13:38 +0530 Subject: [PATCH 01/72] Adds getTarget and list targets controller to user and account --- app/config/errors.php | 5 ++ app/controllers/api/account.php | 50 +++++++++++++++ app/controllers/api/users.php | 62 +++++++++++++++++++ src/Appwrite/Extend/Exception.php | 1 + .../Utopia/Response/Model/BaseList.php | 2 +- 5 files changed, 119 insertions(+), 1 deletion(-) diff --git a/app/config/errors.php b/app/config/errors.php index ed1a9f0aa2..5006df0e89 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -230,6 +230,11 @@ return [ 'description' => 'OAuth2 provider returned some error.', 'code' => 424, ], + Exception::USER_TARGET_NOT_FOUND => [ + 'name' => Exception::USER_TARGET_NOT_FOUND, + 'description' => 'The current user target could not be found.', + 'code' => 404, + ], /** Teams */ Exception::TEAM_NOT_FOUND => [ diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index ce06a807fb..0e69ccdcd9 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1653,6 +1653,29 @@ App::get('/v1/account/logs') ]), Response::MODEL_LOG_LIST); }); +App::get('/v1/account/targets') + ->desc('List Account Targets') + ->groups(['api', 'account']) + ->label('scope', 'account') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'account') + ->label('sdk.method', 'listTargets') + ->label('sdk.description', '/docs/references/account/list-targets.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET_LIST) + ->inject('response') + ->inject('user') + ->action(function (Response $response, Document $user) { + + $targets = $user->getAttribute('targets', []); + + $response->dynamic(new Document([ + 'targets' => $targets, + 'total' => count($targets), + ]), Response::MODEL_TARGET_LIST); + }); + App::get('/v1/account/sessions/:sessionId') ->desc('Get Session') ->groups(['api', 'account']) @@ -1697,6 +1720,33 @@ App::get('/v1/account/sessions/:sessionId') throw new Exception(Exception::USER_SESSION_NOT_FOUND); }); +App::get('/v1/account/targets/:targetId') + ->desc('Get Target') + ->groups(['api', 'account']) + ->label('scope', 'account') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'account') + ->label('sdk.method', 'getTarget') + ->label('sdk.description', '/docs/references/account/get-Target.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk.offline.model', '/account/targets') + ->label('sdk.offline.key', '{targetId}') + ->param('targetId', '', new UID(), 'Target ID.') + ->inject('response') + ->inject('user') + ->action(function (string $targetId, Response $response, Document $user) { + + $target = $user->find('$id', $targetId, 'targets'); + + if (empty($target)) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + + $response->dynamic($target, Response::MODEL_TARGET); + }); + App::patch('/v1/account/name') ->desc('Update Name') ->groups(['api', 'account']) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index c3129d41eb..adc02a3b02 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -461,6 +461,38 @@ App::get('/v1/users/:userId/prefs') $response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES); }); +App::get('/v1/users/:userId/targets/:targetId') + ->desc('Get User Target') + ->groups(['api', 'users']) + ->label('scope', 'users.read') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'users') + ->label('sdk.method', 'getTarget') + ->label('sdk.description', '/docs/references/users/get-user-target.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET) + ->param('userId', '', new UID(), 'User ID.') + ->param('targetId', '', new UID(), 'Target ID.') + ->inject('response') + ->inject('dbForProject') + ->action(function (string $userId, string $targetId, Response $response, Database $dbForProject) { + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $user->find('$id', $targetId, 'targets'); + + if (empty($target)) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + + $response->dynamic($target, Response::MODEL_TARGET); + }); + App::get('/v1/users/:userId/sessions') ->desc('List User Sessions') ->groups(['api', 'users']) @@ -622,6 +654,36 @@ App::get('/v1/users/:userId/logs') ]), Response::MODEL_LOG_LIST); }); +App::get('/v1/users/:userId/targets') + ->desc('List User Targets') + ->groups(['api', 'users']) + ->label('scope', 'users.read') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'users') + ->label('sdk.method', 'listTargets') + ->label('sdk.description', '/docs/references/users/list-user-targets.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET_LIST) + ->param('userId', '', new UID(), 'User ID.') + ->inject('response') + ->inject('dbForProject') + ->action(function (string $userId, Response $response, Database $dbForProject) { + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $targets = $user->getAttribute('targets', []); + var_dump($user); + $response->dynamic(new Document([ + 'targets' => $targets, + 'total' => count($targets), + ]), Response::MODEL_TARGET_LIST); + }); + App::patch('/v1/users/:userId/status') ->desc('Update User Status') ->groups(['api', 'users']) diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 6b448db8ec..1392faaed6 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -81,6 +81,7 @@ class Exception extends \Exception public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; + public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; /** Teams */ public const TEAM_NOT_FOUND = 'team_not_found'; diff --git a/src/Appwrite/Utopia/Response/Model/BaseList.php b/src/Appwrite/Utopia/Response/Model/BaseList.php index 06a5249388..0c2cc072f3 100644 --- a/src/Appwrite/Utopia/Response/Model/BaseList.php +++ b/src/Appwrite/Utopia/Response/Model/BaseList.php @@ -34,7 +34,7 @@ class BaseList extends Model $namesWithCap = [ 'documents', 'collections', 'users', 'files', 'buckets', 'functions', 'deployments', 'executions', 'projects', 'webhooks', 'keys', - 'platforms', 'domains', 'memberships', 'teams' + 'platforms', 'domains', 'memberships', 'teams', 'targets' ]; if (\in_array($name, $namesWithCap)) { From e53f189b3b455f71873d752a4010ede92bc2a0fb Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 16 Aug 2023 20:17:36 +0530 Subject: [PATCH 02/72] lint fix --- app/controllers/api/users.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index adc02a3b02..c1b664ca26 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -483,7 +483,7 @@ App::get('/v1/users/:userId/targets/:targetId') if ($user->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } - + $target = $user->find('$id', $targetId, 'targets'); if (empty($target)) { @@ -491,7 +491,7 @@ App::get('/v1/users/:userId/targets/:targetId') } $response->dynamic($target, Response::MODEL_TARGET); - }); + }); App::get('/v1/users/:userId/sessions') ->desc('List User Sessions') @@ -675,7 +675,7 @@ App::get('/v1/users/:userId/targets') if ($user->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } - + $targets = $user->getAttribute('targets', []); var_dump($user); $response->dynamic(new Document([ From 07b7a9db0f33ced450ec4a469269548526eb581b Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 17 Aug 2023 17:24:45 +0530 Subject: [PATCH 03/72] adds controller for creating a user target --- app/config/collections.php | 6 +-- app/config/errors.php | 14 ++++++- app/config/roles.php | 4 ++ app/controllers/api/account.php | 2 +- app/controllers/api/users.php | 63 ++++++++++++++++++++++++++++++- app/init.php | 19 ++++++++++ src/Appwrite/Extend/Exception.php | 5 ++- 7 files changed, 105 insertions(+), 8 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index f6fff4c474..929a8572b9 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1704,16 +1704,16 @@ $commonCollections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => true, + 'required' => false, 'default' => null, 'array' => false, - 'filters' => [], + 'filters' => ['subQueryProviderType'], ], [ '$id' => ID::custom('identifier'), 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 2048, + 'size' => Database::LENGTH_KEY, 'signed' => true, 'required' => true, 'default' => null, diff --git a/app/config/errors.php b/app/config/errors.php index 5006df0e89..9e8bdd2da7 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -232,7 +232,12 @@ return [ ], Exception::USER_TARGET_NOT_FOUND => [ 'name' => Exception::USER_TARGET_NOT_FOUND, - 'description' => 'The current user target could not be found.', + 'description' => 'The target could not be found.', + 'code' => 404, + ], + Exception::USER_TARGET_ALREADY_EXISTS => [ + 'name' => Exception::USER_TARGET_ALREADY_EXISTS, + 'description' => 'A target with the same ID already exists.', 'code' => 404, ], @@ -664,4 +669,11 @@ return [ 'description' => 'Too many queries.', 'code' => 400, ], + + /** Provider Errors */ + Exception::PROVIDER_NOT_FOUND => [ + 'name' => Exception::PROVIDER_NOT_FOUND, + 'description' => 'Provider with the request ID could not be found.', + 'code' => 400, + ], ]; diff --git a/app/config/roles.php b/app/config/roles.php index f0039841d2..8574a1392c 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -20,6 +20,8 @@ $member = [ 'avatars.read', 'execution.read', 'execution.write', + 'targets.read', + 'targets.write', ]; $admins = [ @@ -51,6 +53,8 @@ $admins = [ 'functions.write', 'execution.read', 'execution.write', + 'targets.read', + 'targets.write', ]; return [ diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 0e69ccdcd9..64fe71a0dd 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1672,7 +1672,7 @@ App::get('/v1/account/targets') $response->dynamic(new Document([ 'targets' => $targets, - 'total' => count($targets), + 'total' => \count($targets), ]), Response::MODEL_TARGET_LIST); }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index c1b664ca26..2290a77c3e 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -363,6 +363,66 @@ App::post('/v1/users/scrypt-modified') ->dynamic($user, Response::MODEL_USER); }); +App::post('/v1/users/:userId/targets') + ->desc('Create User Target') + ->groups(['api', 'users']) + ->label('event', 'users.[userId].targets.[targetId].create') + ->label('scope', 'targets.write') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'users') + ->label('sdk.method', 'createTarget') + ->label('sdk.description', '/docs/references/users/create-target.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET) + ->param('targetId', '', new UID(), 'Target ID.', false) + ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('providerId', '', new UID(), 'ID of the provider.', false) + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', false) + ->inject('response') + ->inject('project') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $targetId, string $userId, string $providerId, string $identifier, Response $response, Document $project, Database $dbForProject, Event $events) { + $provider = $dbForProject->getDocument('providers', $providerId); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + + $user = $dbForProject->getDocument('users', $userId); + + if($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $dbForProject->getDocument('targets', $targetId); + + if(!$target->isEmpty()) { + throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); + } + + $target = $dbForProject->createDocument('targets', new Document([ + '$id' => $targetId, + // TO DO: what permissions should be given when created a target. + '$permissions' => [ + Permission::read(Role::any()) + ], + 'providerId' => $providerId, + 'providerInternalId' => $provider->getInternalId(), + 'providerType' => null, + 'userId' => $userId, + 'userInternalId' => $user->getInternalId(), + 'identifier' => $identifier, + ])); + $events + ->setParam('userId', $userId) + ->setParam('targetId', $targetId); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($target, Response::MODEL_TARGET); + }); + App::get('/v1/users') ->desc('List Users') ->groups(['api', 'users']) @@ -677,10 +737,9 @@ App::get('/v1/users/:userId/targets') } $targets = $user->getAttribute('targets', []); - var_dump($user); $response->dynamic(new Document([ 'targets' => $targets, - 'total' => count($targets), + 'total' => \count($targets), ]), Response::MODEL_TARGET_LIST); }); diff --git a/app/init.php b/app/init.php index 65cf4034a6..46b19cbe16 100644 --- a/app/init.php +++ b/app/init.php @@ -535,6 +535,25 @@ Database::addFilter( ])); } ); + +Database::addFilter( + 'subQueryProviderType', + function (mixed $value) { + return null; + }, + function (mixed $value, Document $document, Database $database) { + $provider = Authorization::skip(fn() => $database + ->findOne('providers', [ + Query::equal('$id', [$document->getAttribute('providerId')]), + Query::select(['type']), + Query::limit(APP_LIMIT_SUBQUERY), + ])); + if($provider) + return $provider->getAttribute('type'); + return null; + } +); + /** * DB Formats */ diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 1392faaed6..92bbd5c6c4 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -82,7 +82,7 @@ class Exception extends \Exception public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; - + public const USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; /** Teams */ public const TEAM_NOT_FOUND = 'team_not_found'; public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; @@ -205,6 +205,9 @@ class Exception extends \Exception public const GRAPHQL_NO_QUERY = 'graphql_no_query'; public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; + /** Provider */ + public const PROVIDER_NOT_FOUND = 'provider_not_found'; + protected $type = ''; protected $errors = []; From c83e4db23d15fb210dcc6dd913e58263f91e927e Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 17 Aug 2023 19:02:07 +0530 Subject: [PATCH 04/72] lint fix --- app/controllers/api/users.php | 4 ++-- app/init.php | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 2290a77c3e..d47024f81e 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -392,13 +392,13 @@ App::post('/v1/users/:userId/targets') $user = $dbForProject->getDocument('users', $userId); - if($user->isEmpty()) { + if ($user->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } $target = $dbForProject->getDocument('targets', $targetId); - if(!$target->isEmpty()) { + if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); } diff --git a/app/init.php b/app/init.php index 46b19cbe16..233e022a1e 100644 --- a/app/init.php +++ b/app/init.php @@ -548,8 +548,9 @@ Database::addFilter( Query::select(['type']), Query::limit(APP_LIMIT_SUBQUERY), ])); - if($provider) + if ($provider) { return $provider->getAttribute('type'); + } return null; } ); From f73b3bf2723a4c761c6df017962c1abc02bbe7a6 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 18 Aug 2023 01:07:42 +0530 Subject: [PATCH 05/72] deletes user cache document --- app/controllers/api/users.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d47024f81e..b66429d9ba 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -380,10 +380,9 @@ App::post('/v1/users/:userId/targets') ->param('providerId', '', new UID(), 'ID of the provider.', false) ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', false) ->inject('response') - ->inject('project') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, string $providerId, string $identifier, Response $response, Document $project, Database $dbForProject, Event $events) { + ->action(function (string $targetId, string $userId, string $providerId, string $identifier, Response $response, Database $dbForProject, Event $events) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -415,6 +414,7 @@ App::post('/v1/users/:userId/targets') 'userInternalId' => $user->getInternalId(), 'identifier' => $identifier, ])); + $dbForProject->deleteCachedDocument('users', $user->getId()); $events ->setParam('userId', $userId) ->setParam('targetId', $targetId); From 36a5d1e245ca2f3ea131ad18f92c31845d4e961b Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 18 Aug 2023 23:28:12 +0530 Subject: [PATCH 06/72] adds remaining controllers for target in account and users --- app/controllers/api/account.php | 153 ++++++++++++++++++++++++++++++++ app/controllers/api/users.php | 101 ++++++++++++++++++++- composer.lock | 22 ++--- 3 files changed, 261 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 64fe71a0dd..d9749f0274 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2818,3 +2818,156 @@ App::put('/v1/account/verification/phone') $response->dynamic($verificationDocument, Response::MODEL_TOKEN); }); + +App::post('/v1/account/targets') + ->desc('Create User Target') + ->groups(['api', 'account']) + ->label('event', 'users.[userId].targets.[targetId].create') + ->label('scope', 'targets.write') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'account') + ->label('sdk.method', 'createTarget') + ->label('sdk.description', '/docs/references/account/create-target.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET) + ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('targetId', '', new UID(), 'Target ID.', false) + ->param('providerId', '', new UID(), 'ID of the provider.', false) + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', false) + ->inject('response') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $targetId, string $userId, string $providerId, string $identifier, Response $response, Database $dbForProject, Event $events) { + $provider = $dbForProject->getDocument('providers', $providerId); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $dbForProject->getDocument('targets', $targetId); + + if (!$target->isEmpty()) { + throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); + } + + $target = $dbForProject->createDocument('targets', new Document([ + '$id' => $targetId, + // TO DO: what permissions should be given when created a target. + '$permissions' => [ + Permission::read(Role::any()) + ], + 'providerId' => $providerId, + 'providerInternalId' => $provider->getInternalId(), + 'providerType' => null, + 'userId' => $userId, + 'userInternalId' => $user->getInternalId(), + 'identifier' => $identifier, + ])); + $dbForProject->deleteCachedDocument('users', $user->getId()); + $events + ->setParam('userId', $userId) + ->setParam('targetId', $targetId); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($target, Response::MODEL_TARGET); + }); + +App::patch('/v1/account/targets/:targetId/identifier') + ->desc('Update user target\'s identifier') + ->groups(['api', 'account']) + ->label('event', 'users.[userId].targets.[targetId].update') + ->label('scope', 'targets.write') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'account') + ->label('sdk.method', 'updateTargetIdentifier') + ->label('sdk.description', '/docs/references/account/update-target-identifier.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET) + ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('targetId', '', new UID(), 'Target ID.', false) + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true) + ->inject('response') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $dbForProject->getDocument('targets', $targetId); + + if ($target->isEmpty()) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + + // Update the target identifier here + $target->setAttribute('identifier', $identifier); + + $target = $dbForProject->updateDocument('targets', $target->getId(), $target); + $dbForProject->deleteCachedDocument('users', $user->getId()); + + $events + ->setParam('userId', $userId) + ->setParam('targetId', $targetId); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($target, Response::MODEL_TARGET); + }); + +App::delete('/v1/account/targets/:targetId') + ->desc('Delete user target') + ->groups(['api', 'account']) + ->label('event', 'users.[userId].targets.[targetId].delete') + ->label('scope', 'targets.write') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'account') + ->label('sdk.method', 'deleteTarget') + ->label('sdk.description', '/docs/references/account/delete-target.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_NONE) + ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('targetId', '', new UID(), 'Target ID.', false) + ->inject('response') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $dbForProject->getDocument('targets', $targetId); + + if ($target->isEmpty()) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + + $target = $dbForProject->deleteDocument('targets', $target->getId()); + $dbForProject->deleteCachedDocument('users', $user->getId()); + $user = $dbForProject->getDocument('users', $userId); + + // clone user object to send to workers + $clone = clone $user; + + $events + ->setParam('userId', $userId) + ->setParam('targetId', $targetId) + ->setPayload($response->output($clone, Response::MODEL_USER)); + + $response->noContent(); + }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index b66429d9ba..86f25579ca 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -368,15 +368,15 @@ App::post('/v1/users/:userId/targets') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].create') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'createTarget') ->label('sdk.description', '/docs/references/users/create-target.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('targetId', '', new UID(), 'Target ID.', false) ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('targetId', '', new UID(), 'Target ID.', false) ->param('providerId', '', new UID(), 'ID of the provider.', false) ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', false) ->inject('response') @@ -525,7 +525,7 @@ App::get('/v1/users/:userId/targets/:targetId') ->desc('Get User Target') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'getTarget') ->label('sdk.description', '/docs/references/users/get-user-target.md') @@ -718,7 +718,7 @@ App::get('/v1/users/:userId/targets') ->desc('List User Targets') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'listTargets') ->label('sdk.description', '/docs/references/users/list-user-targets.md') @@ -1147,6 +1147,53 @@ App::patch('/v1/users/:userId/prefs') $response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES); }); +App::patch('/v1/users/:userId/targets/:targetId/identifier') + ->desc('Update user target\'s identifier') + ->groups(['api', 'users']) + ->label('event', 'users.[userId].targets.[targetId].update') + ->label('scope', 'targets.write') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'users') + ->label('sdk.method', 'updateTargetIdentifier') + ->label('sdk.description', '/docs/references/users/update-target-identifier.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_TARGET) + ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('targetId', '', new UID(), 'Target ID.', false) + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true) + ->inject('response') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $dbForProject->getDocument('targets', $targetId); + + if ($target->isEmpty()) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + + // Update the target identifier here + $target->setAttribute('identifier', $identifier); + + $target = $dbForProject->updateDocument('targets', $target->getId(), $target); + $dbForProject->deleteCachedDocument('users', $user->getId()); + + $events + ->setParam('userId', $userId) + ->setParam('targetId', $targetId); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($target, Response::MODEL_TARGET); + }); + App::delete('/v1/users/:userId/sessions/:sessionId') ->desc('Delete User Session') ->groups(['api', 'users']) @@ -1274,6 +1321,52 @@ App::delete('/v1/users/:userId') $response->noContent(); }); +App::delete('/v1/users/:userId/targets/:targetId') + ->desc('Delete user target') + ->groups(['api', 'users']) + ->label('event', 'users.[userId].targets.[targetId].delete') + ->label('scope', 'targets.write') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'users') + ->label('sdk.method', 'deleteTarget') + ->label('sdk.description', '/docs/references/users/delete-target.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_NONE) + ->param('userId', '', new UID(), 'ID of the user.', false) + ->param('targetId', '', new UID(), 'Target ID.', false) + ->inject('response') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { + + $user = $dbForProject->getDocument('users', $userId); + + if ($user->isEmpty()) { + throw new Exception(Exception::USER_NOT_FOUND); + } + + $target = $dbForProject->getDocument('targets', $targetId); + + if ($target->isEmpty()) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + + $target = $dbForProject->deleteDocument('targets', $target->getId()); + $dbForProject->deleteCachedDocument('users', $user->getId()); + $user = $dbForProject->getDocument('users', $userId); + + // clone user object to send to workers + $clone = clone $user; + + $events + ->setParam('userId', $userId) + ->setParam('targetId', $targetId) + ->setPayload($response->output($clone, Response::MODEL_USER)); + + $response->noContent(); + }); + App::get('/v1/users/usage') ->desc('Get usage stats for the users API') ->groups(['api', 'users', 'usage']) diff --git a/composer.lock b/composer.lock index 0e72c867d2..579029b79c 100644 --- a/composer.lock +++ b/composer.lock @@ -686,16 +686,16 @@ }, { "name": "matomo/device-detector", - "version": "6.1.4", + "version": "6.1.5", "source": { "type": "git", "url": "https://github.com/matomo-org/device-detector.git", - "reference": "74f6c4f6732b3ad6cdf25560746841d522969112" + "reference": "40ca2990dba2c1719e5c62168e822e0b86c167d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/74f6c4f6732b3ad6cdf25560746841d522969112", - "reference": "74f6c4f6732b3ad6cdf25560746841d522969112", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/40ca2990dba2c1719e5c62168e822e0b86c167d4", + "reference": "40ca2990dba2c1719e5c62168e822e0b86c167d4", "shasum": "" }, "require": { @@ -751,7 +751,7 @@ "source": "https://github.com/matomo-org/matomo", "wiki": "https://dev.matomo.org/" }, - "time": "2023-08-02T08:48:53+00:00" + "time": "2023-08-17T16:17:41+00:00" }, { "name": "mongodb/mongodb", @@ -1516,16 +1516,16 @@ }, { "name": "utopia-php/database", - "version": "0.42.1", + "version": "0.42.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "9ff69a9b9eadc581771798833d423829c9d8cc90" + "reference": "bc5ceb30c85fb685b0b5704d2f74886d813ebd41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/9ff69a9b9eadc581771798833d423829c9d8cc90", - "reference": "9ff69a9b9eadc581771798833d423829c9d8cc90", + "url": "https://api.github.com/repos/utopia-php/database/zipball/bc5ceb30c85fb685b0b5704d2f74886d813ebd41", + "reference": "bc5ceb30c85fb685b0b5704d2f74886d813ebd41", "shasum": "" }, "require": { @@ -1566,9 +1566,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.42.1" + "source": "https://github.com/utopia-php/database/tree/0.42.2" }, - "time": "2023-08-14T16:09:09+00:00" + "time": "2023-08-17T19:04:37+00:00" }, { "name": "utopia-php/domains", From fe8b8d3dc686555648b7cea9a768a179f96e7408 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Mon, 21 Aug 2023 14:14:06 +0530 Subject: [PATCH 07/72] fix lint --- app/controllers/api/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 8bf107b5ee..e6d5e8e1b9 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1530,4 +1530,4 @@ App::get('/v1/users/usage') 'usersTotal' => $usage[$metrics[0]], 'sessionsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_USERS); - }); \ No newline at end of file + }); From a6d613542bfaa0845f8ec2f1ccad03ffa5c101b6 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Mon, 21 Aug 2023 16:14:50 +0530 Subject: [PATCH 08/72] adds messaging api controlle for mailgun provider --- app/config/services.php | 13 ++++++++++ app/controllers/api/messaging.php | 42 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 app/controllers/api/messaging.php diff --git a/app/config/services.php b/app/config/services.php index e14a1d5781..f80431f784 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -225,4 +225,17 @@ return [ 'optional' => true, 'icon' => '/images/services/migrations.png', ], + 'messaging' => [ + 'key' => 'messaging', + 'name' => 'Messaging', + 'subtitle' => 'The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).', + 'description' => '/docs/services/messaging.md', + 'controller' => 'api/messaging.php', + 'sdk' => true, + 'docs' => true, + 'docsUrl' => 'https://appwrite.io/docs/server/messaging', + 'tests' => false, + 'optional' => true, + 'icon' => '/images/services/messaging.png', + ] ]; diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php new file mode 100644 index 0000000000..2f0c50348a --- /dev/null +++ b/app/controllers/api/messaging.php @@ -0,0 +1,42 @@ +desc('Create Mailgun Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.description', '/docs/references/messaging/create-provider-mailgun.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('apiKey', null, new Text(0), 'Mailgun API Key.', true) + ->param('domain', null, new Text(0), 'Mailgun Domain.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', '64e33e70dd07f0d03efb'); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'Mailgun', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + 'domain' => $domain + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); From 4406c7bd554eedb63e764c03a01822ca1fd344e1 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Mon, 21 Aug 2023 22:15:15 +0530 Subject: [PATCH 09/72] adds messaging worker and send an email controller --- app/controllers/api/messaging.php | 55 +++++++++++++- app/workers/messaging.php | 118 ++++++++++++++++++++---------- composer.json | 4 +- composer.lock | 67 ++++++++++------- 4 files changed, 175 insertions(+), 69 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 2f0c50348a..f5ee54c852 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1,9 +1,13 @@ inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', '64e33e70dd07f0d03efb'); $provider = $dbForProject->createDocument('providers', new Document([ 'name' => $name, 'provider' => 'Mailgun', @@ -40,3 +43,53 @@ App::post('/v1/messaging/providers/mailgun') ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); + +App::post('/v1/messaging/messages/email') + ->desc('Send an email.') + ->groups(['api', 'messaging']) + ->label('event', 'messages.create') + ->label('scope', 'messages.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.description', '/docs/references/messaging/send-email.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->param('providerId', '', new Text(128), 'Email Provider ID.') + ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.', true) + ->param('subject', null, new Text(0), 'Email Subject.', true) + ->param('content', null, new Text(0), 'Email Content.', true) + ->param('from', null, new Text(0), 'Email from.', false) + ->param('html', null, new Text(0), 'Is content of type HTML', false) + ->param('deliveryTime', null, new Datetime(), 'Delivery time of the message', false) + ->inject('dbForProject') + ->inject('events') + ->inject('response') + ->action(function (string $providerId, string $to, string $subject, string $content, string $from, string $html, DateTime $deliveryTime, Database $dbForProject, Event $eventsInstance, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + + $message = $dbForProject->createDocument('messages', new Document([ + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'to' => $to, + 'data' => [ + 'subject' => $subject, + 'content' => $content, + ], + 'deliveryTime' => $deliveryTime, + 'deliveryError' => null, + 'deliveredTo' => null, + 'delivered' => false, + 'search' => null + ])); + + $eventsInstance->setParam('messageId', $message->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_MESSAGE); + }); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 5732c8c00b..3e730b120a 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -1,17 +1,23 @@ getAttribute('credentials'); + return match ($record->getAttribute('provider')) { + 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), + 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), + 'telesign' => new Telesign($credentials['username'], $credentials['password']), + 'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']), + 'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']), + default => null + }; + } + + function push($record): ?PushAdapter + { + $credentials = $record->getAttribute('credentials'); + return match ($record->getAttribute('provider')) { + 'apns' => new APNS( + $credentials['authKey'], + $credentials['authKeyId'], + $credentials['teamId'], + $credentials['bundleId'], + $credentials['endpoint'] + ), + 'fcm' => new FCM($credentials['serverKey']), + default => null + }; + } + + public function email($record): ?EmailAdapter + { + $credentials = $record->getAttribute('credentials'); + return match ($record->getAttribute('provider')) { + 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain']), + 'sendgrid' => new SendGrid($credentials['apiKey']), + default => null + }; + } + public function init(): void { - $dsn = new DSN(App::getEnv('_APP_SMS_PROVIDER')); - $user = $dsn->getUser(); - $secret = $dsn->getPassword(); - - $this->sms = match ($dsn->getHost()) { - 'mock' => new Mock($user, $secret), // used for tests - 'twilio' => new Twilio($user, $secret), - 'text-magic' => new TextMagic($user, $secret), - 'telesign' => new Telesign($user, $secret), - 'msg91' => new Msg91($user, $secret), - 'vonage' => new Vonage($user, $secret), - default => null - }; - - $this->from = App::getEnv('_APP_SMS_FROM'); } public function run(): void { - if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { - Console::info('Skipped sms processing. No Phone provider has been set.'); - return; - } + $providerId = $this->args['providerId']; + $providerRecord = + $this + ->getConsoleDB() + ->getDocument('providers', $providerId); - if (empty($this->from)) { - Console::info('Skipped sms processing. No phone number has been set.'); - return; - } + $provider = match ($providerRecord->getAttribute('type')) {//stubbbbbbed. + 'sms' => $this->sms($providerRecord), + 'push' => $this->push($providerRecord), + 'email' => $this->email($providerRecord), + default => null + }; - $message = new SMS( - to: [$this->args['recipient']], - content: $this->args['message'], - from: $this->from, - ); + // Query for the provider + // switch on provider name + // call function passing needed credentials returns required provider. - try { - $this->sms->send($message); - } catch (\Exception $error) { - throw new Exception('Error sending message: ' . $error->getMessage(), 500); - } + $messageId = $this->args['messageId']; + $message = + $this + ->getConsoleDB() + ->getDocument('messages', $messageId); + + // Contrust Message Object according to each provider type. + // Send the message using respective adapter } - public function shutdown(): void + function shutdown(): void { } } diff --git a/composer.json b/composer.json index 2fd93cf510..e73d67b6a7 100644 --- a/composer.json +++ b/composer.json @@ -50,13 +50,13 @@ "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", "utopia-php/database": "0.42.*", - "utopia-php/domains": "1.1.*", + "utopia-php/domains": "0.3.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.28.*", "utopia-php/image": "0.5.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.3.*", - "utopia-php/messaging": "0.1.*", + "utopia-php/messaging": "dev-feat-push as 0.1.1", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.4.*", "utopia-php/pools": "0.4.*", diff --git a/composer.lock b/composer.lock index cf6f442954..55e84a6e74 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": "2098172fc4b71eb0d41dcdbfea2f5061", + "content-hash": "d599591131c16b547bb7ad8c83a35482", "packages": [ { "name": "adhocore/jwt", @@ -1557,16 +1557,16 @@ }, { "name": "utopia-php/database", - "version": "0.42.1", + "version": "0.42.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "9ff69a9b9eadc581771798833d423829c9d8cc90" + "reference": "bc5ceb30c85fb685b0b5704d2f74886d813ebd41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/9ff69a9b9eadc581771798833d423829c9d8cc90", - "reference": "9ff69a9b9eadc581771798833d423829c9d8cc90", + "url": "https://api.github.com/repos/utopia-php/database/zipball/bc5ceb30c85fb685b0b5704d2f74886d813ebd41", + "reference": "bc5ceb30c85fb685b0b5704d2f74886d813ebd41", "shasum": "" }, "require": { @@ -1607,29 +1607,31 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.42.1" + "source": "https://github.com/utopia-php/database/tree/0.42.2" }, - "time": "2023-08-14T16:09:09+00:00" + "time": "2023-08-17T19:04:37+00:00" }, { "name": "utopia-php/domains", - "version": "v1.1.0", + "version": "0.3.2", "source": { "type": "git", "url": "https://github.com/utopia-php/domains.git", - "reference": "1665e1d9932afa3be63b5c1e0dcfe01fe77d8e73" + "reference": "aaa8c9a96c69ccb397997b1f4f2299c66f77eefb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/domains/zipball/1665e1d9932afa3be63b5c1e0dcfe01fe77d8e73", - "reference": "1665e1d9932afa3be63b5c1e0dcfe01fe77d8e73", + "url": "https://api.github.com/repos/utopia-php/domains/zipball/aaa8c9a96c69ccb397997b1f4f2299c66f77eefb", + "reference": "aaa8c9a96c69ccb397997b1f4f2299c66f77eefb", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.0", + "utopia-php/framework": "0.*.*" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "laravel/pint": "1.2.*", + "phpunit/phpunit": "^9.3" }, "type": "library", "autoload": { @@ -1645,6 +1647,10 @@ { "name": "Eldad Fux", "email": "eldad@appwrite.io" + }, + { + "name": "Wess Cope", + "email": "wess@appwrite.io" } ], "description": "Utopia Domains library is simple and lite library for parsing web domains. This library is aiming to be as simple and easy to learn and use.", @@ -1661,9 +1667,9 @@ ], "support": { "issues": "https://github.com/utopia-php/domains/issues", - "source": "https://github.com/utopia-php/domains/tree/master" + "source": "https://github.com/utopia-php/domains/tree/0.3.2" }, - "time": "2020-02-23T07:40:02+00:00" + "time": "2023-07-19T16:39:24+00:00" }, { "name": "utopia-php/dsn", @@ -1915,16 +1921,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.1.1", + "version": "dev-feat-push", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "a75d66ddd59b834ab500a4878a2c084e6572604a" + "reference": "5f85757316eb842e9169d318e234124ff252c404" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/a75d66ddd59b834ab500a4878a2c084e6572604a", - "reference": "a75d66ddd59b834ab500a4878a2c084e6572604a", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/5f85757316eb842e9169d318e234124ff252c404", + "reference": "5f85757316eb842e9169d318e234124ff252c404", "shasum": "" }, "require": { @@ -1933,8 +1939,8 @@ }, "require-dev": { "laravel/pint": "^1.2", - "phpmailer/phpmailer": "6.6.*", - "phpunit/phpunit": "9.5.*" + "phpmailer/phpmailer": "^6.8", + "phpunit/phpunit": "^9.6" }, "type": "library", "autoload": { @@ -1957,9 +1963,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.1.1" + "source": "https://github.com/utopia-php/messaging/tree/feat-push" }, - "time": "2023-02-07T05:42:46+00:00" + "time": "2023-08-14T20:35:31+00:00" }, { "name": "utopia-php/migration", @@ -5351,9 +5357,18 @@ "time": "2023-07-26T07:16:09+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/messaging", + "version": "dev-feat-push", + "alias": "0.1.1", + "alias_normalized": "0.1.1.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/messaging": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -5377,5 +5392,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } From 9f19bec7a74f090f15e996a7521b377ae355f48d Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 22 Aug 2023 18:21:30 +0530 Subject: [PATCH 10/72] lint fix --- app/controllers/api/messaging.php | 5 ++-- app/workers/messaging.php | 42 ++++++++++++++----------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index f5ee54c852..8d1c13492e 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -11,8 +11,9 @@ use Utopia\Validator\ArrayList; use Utopia\Validator\Text; /** - * Email Providers + * Email Providers */ + App::post('/v1/messaging/providers/mailgun') ->desc('Create Mailgun Provider') ->groups(['api', 'messaging']) @@ -69,7 +70,7 @@ App::post('/v1/messaging/messages/email') $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $message = $dbForProject->createDocument('messages', new Document([ diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 3e730b120a..5fba550baa 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -2,23 +2,19 @@ use Appwrite\Resque\Worker; use Utopia\CLI\Console; - use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Adapters\SMS\Msg91; use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; use Utopia\Messaging\Adapters\SMS\Twilio; use Utopia\Messaging\Adapters\SMS\Vonage; - use Utopia\Messaging\Adapters\Push as PushAdapter; use Utopia\Messaging\Adapters\Push\APNS; use Utopia\Messaging\Adapters\Push\FCM; - use Utopia\Messaging\Adapters\Email as EmailAdapter; use Utopia\Messaging\Adapters\Email\Mailgun; use Utopia\Messaging\Adapters\Email\SendGrid; - require_once __DIR__ . '/../init.php'; Console::title('Messaging V1 Worker'); @@ -29,8 +25,8 @@ class MessagingV1 extends Worker protected ?SMSAdapter $sms = null; protected ?PushAdapter $push = null; protected ?EmailAdapter $email = null; - - + + protected ?string $from = null; public function getName(): string @@ -48,7 +44,7 @@ class MessagingV1 extends Worker 'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']), 'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']), default => null - }; + }; } function push($record): ?PushAdapter @@ -56,15 +52,15 @@ class MessagingV1 extends Worker $credentials = $record->getAttribute('credentials'); return match ($record->getAttribute('provider')) { 'apns' => new APNS( - $credentials['authKey'], - $credentials['authKeyId'], - $credentials['teamId'], - $credentials['bundleId'], + $credentials['authKey'], + $credentials['authKeyId'], + $credentials['teamId'], + $credentials['bundleId'], $credentials['endpoint'] ), 'fcm' => new FCM($credentials['serverKey']), default => null - }; + }; } public function email($record): ?EmailAdapter @@ -74,7 +70,7 @@ class MessagingV1 extends Worker 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain']), 'sendgrid' => new SendGrid($credentials['apiKey']), default => null - }; + }; } public function init(): void @@ -83,25 +79,25 @@ class MessagingV1 extends Worker public function run(): void { - $providerId = $this->args['providerId']; - $providerRecord = + $providerId = $this->args['providerId']; + $providerRecord = $this ->getConsoleDB() ->getDocument('providers', $providerId); - $provider = match ($providerRecord->getAttribute('type')) {//stubbbbbbed. - 'sms' => $this->sms($providerRecord), - 'push' => $this->push($providerRecord), - 'email' => $this->email($providerRecord), - default => null - }; + $provider = match ($providerRecord->getAttribute('type')) {//stubbbbbbed. + 'sms' => $this->sms($providerRecord), + 'push' => $this->push($providerRecord), + 'email' => $this->email($providerRecord), + default => null + }; // Query for the provider // switch on provider name // call function passing needed credentials returns required provider. - $messageId = $this->args['messageId']; - $message = + $messageId = $this->args['messageId']; + $message = $this ->getConsoleDB() ->getDocument('messages', $messageId); From 78385a59c6ddd286d4d28cff98d8745f2c1e1caf Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 22 Aug 2023 22:15:31 +0530 Subject: [PATCH 11/72] adds remaining provider controllers --- app/config/errors.php | 6 +- app/controllers/api/account.php | 7 +- app/controllers/api/messaging.php | 861 +++++++++++++++++- app/controllers/api/users.php | 7 +- src/Appwrite/Extend/Exception.php | 1 + .../Database/Validator/Queries/Providers.php | 21 + 6 files changed, 885 insertions(+), 18 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Providers.php diff --git a/app/config/errors.php b/app/config/errors.php index 99cde0baee..5942c6027c 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -696,7 +696,11 @@ return [ Exception::PROVIDER_NOT_FOUND => [ 'name' => Exception::PROVIDER_NOT_FOUND, 'description' => 'Provider with the request ID could not be found.', + 'code' => 404, + ], + Exception::PROVIDER_INCORRECT_TYPE => [ + 'name' => Exception::PROVIDER_INCORRECT_TYPE, + 'description' => 'Provider with the request ID is of incorrect type: ', 'code' => 400, - ] ]; diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index e6b0b2addc..46acd2efdb 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3051,8 +3051,7 @@ App::post('/v1/account/targets') ])); $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId) - ->setParam('targetId', $targetId); + ->setParam('userId', $userId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); @@ -3097,8 +3096,7 @@ App::patch('/v1/account/targets/:targetId/identifier') $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId) - ->setParam('targetId', $targetId); + ->setParam('userId', $userId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3145,7 +3143,6 @@ App::delete('/v1/account/targets/:targetId') $events ->setParam('userId', $userId) - ->setParam('targetId', $targetId) ->setPayload($response->output($clone, Response::MODEL_USER)); $response->noContent(); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 8d1c13492e..14065f9097 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2,18 +2,87 @@ use Appwrite\Event\Event; use Appwrite\Extend\Exception; +use Appwrite\Utopia\Database\Validator\Queries\Providers; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime; +use Utopia\Database\Validator\UID; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; +App::get('/v1/messaging/providers') + ->desc('List Providers') + ->groups(['api', 'messaging']) + ->label('scope', 'providers.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'listProviders') + ->label('sdk.description', '/docs/references/messaging/list-providers.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) + ->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) + ->inject('dbForProject') + ->inject('response') + ->action(function (array $queries, Database $dbForProject, Response $response) { + $queries = Query::parseQueries($queries); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); + + if ($cursor) { + $providerId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ + Query::equal('$id', [$providerId]), + Query::limit(1), + ])); + + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument[0]); + } + + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), + 'indexes' => $dbForProject->find('providers', $queries), + ]), Response::MODEL_PROVIDER_LIST); + }); + +App::get('/v1/messaging/providers/:id') + ->desc('Get Provider') + ->groups(['api', 'messaging']) + ->label('scope', 'providers.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'getProvider') + ->label('sdk.description', '/docs/references/messaging/get-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', null, new UID(), 'Provider ID.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, Response $response, Database $dbForProject) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + + $response->dynamic($provider, Response::MODEL_PROVIDER); + }); + /** * Email Providers */ - App::post('/v1/messaging/providers/mailgun') ->desc('Create Mailgun Provider') ->groups(['api', 'messaging']) @@ -21,23 +90,24 @@ App::post('/v1/messaging/providers/mailgun') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderMailgun') ->label('sdk.description', '/docs/references/messaging/create-provider-mailgun.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('name', '', new Text(128), 'Provider name.') - ->param('apiKey', null, new Text(0), 'Mailgun API Key.', true) - ->param('domain', null, new Text(0), 'Mailgun Domain.', true) + ->param('apiKey', '', new Text(0), 'Mailgun API Key.') + ->param('domain', '', new Text(0), 'Mailgun Domain.') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { $provider = $dbForProject->createDocument('providers', new Document([ 'name' => $name, - 'provider' => 'Mailgun', + 'provider' => 'mailgun', 'type' => 'email', 'credentials' => [ 'apiKey' => $apiKey, - 'domain' => $domain + 'domain' => $domain, ], ])); $response @@ -45,6 +115,782 @@ App::post('/v1/messaging/providers/mailgun') ->dynamic($provider, Response::MODEL_PROVIDER); }); +App::patch('/v1/messaging/providers/:id/mailgun') + ->desc('Update Mailgun Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderMailgun') + ->label('sdk.description', '/docs/references/messaging/update-provider-mailgun.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) + ->param('domain', '', new Text(0), 'Mailgun Domain.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'mailgun') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($apiKey || $domain) { + // Check if all five variables are present + if ($apiKey && $domain) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'domain' => $domain + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/sendgrid') + ->desc('Create Sendgrid Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderSendgrid') + ->label('sdk.description', '/docs/references/messaging/create-provider-sendgrid.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('apiKey', '', new Text(0), 'Sendgrid API key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'sendgrid', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/sendgrid') + ->desc('Update Sendgrid Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderSendgrid') + ->label('sdk.description', '/docs/references/messaging/update-provider-sendgrid.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'sendgrid') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($apiKey) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey + ]); + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +/** + * SMS Providers + */ +App::post('/v1/messaging/providers/msg91') + ->desc('Create Msg91 Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderMsg91') + ->label('sdk.description', '/docs/references/messaging/create-provider-msg91.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') + ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'msg91', + 'type' => 'sms', + 'credentials' => [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/msg91') + ->desc('Update Msg91 Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderMsg91') + ->label('sdk.description', '/docs/references/messaging/update-provider-msg91.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) + ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'msg91') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($senderId || $authKey) { + // Check if all five variables are present + if ($senderId && $authKey) { + $provider->setAttribute('credentials', [ + 'senderId' => $senderId, + 'authKey' => $authKey + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/telesign') + ->desc('Create Telesign Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderTelesign') + ->label('sdk.description', '/docs/references/messaging/create-provider-telesign.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('username', '', new Text(0), 'Telesign username.') + ->param('password', '', new Text(0), 'Telesign password.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $username, string $password, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'telesign', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'password' => $password, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/telesign') + ->desc('Update Telesign Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderTelesign') + ->label('sdk.description', '/docs/references/messaging/update-provider-telesign.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('username', '', new Text(0), 'Telesign username.', true) + ->param('password', '', new Text(0), 'Telesign password.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'telesign') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($username || $password) { + // Check if all five variables are present + if ($username && $password) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'password' => $password + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/textmagic') + ->desc('Create Textmagic Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderTextmagic') + ->label('sdk.description', '/docs/references/messaging/create-provider-textmagic.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('username', '', new Text(0), 'Textmagic username.') + ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'text-magic', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/textmagic') + ->desc('Update Textmagic Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderTextmagic') + ->label('sdk.description', '/docs/references/messaging/update-provider-textmagic.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('username', '', new Text(0), 'Textmagic username.', true) + ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'text-magic') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($username || $apiKey) { + // Check if all five variables are present + if ($username && $apiKey) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'apiKey' => $apiKey + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/twilio') + ->desc('Create Twilio Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderTwilio') + ->label('sdk.description', '/docs/references/messaging/create-provider-twilio.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') + ->param('authToken', '', new Text(0), 'Twilio authentication token.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'twilio', + 'type' => 'sms', + 'credentials' => [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/twilio') + ->desc('Update Twilio Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderTwilio') + ->label('sdk.description', '/docs/references/messaging/update-provider-twilio.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) + ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'twilio') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($accountSid || $authToken) { + // Check if all five variables are present + if ($accountSid && $authToken) { + $provider->setAttribute('credentials', [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/vonage') + ->desc('Create Vonage Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderVonage') + ->label('sdk.description', '/docs/references/messaging/create-provider-vonage.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('apiKey', '', new Text(0), 'Vonage API key.') + ->param('apiSecret', '', new Text(0), 'Vonage API secret.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'vonage', + 'type' => 'sms', + 'credentials' => [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/vonage') + ->desc('Update Vonage Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderVonage') + ->label('sdk.description', '/docs/references/messaging/update-provider-vonage.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('apiKey', '', new Text(0), 'Vonage API key.', true) + ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'vonage') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($apiKey || $apiSecret) { + // Check if all five variables are present + if ($apiKey && $apiSecret) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +/** + * Push Providers + */ +App::post('/v1/messaging/providers/fcm') + ->desc('Create FCM Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderFCM') + ->label('sdk.description', '/docs/references/messaging/create-provider-fcm.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('serverKey', '', new Text(0), 'FCM Server Key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $serverKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'fcm', + 'type' => 'push', + 'credentials' => [ + 'serverKey' => $serverKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/fcm') + ->desc('Update FCM Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderFCM') + ->label('sdk.description', '/docs/references/messaging/update-provider-fcm.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'fcm') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($serverKey) { + $provider->setAttribute('credentials', ['serverKey' => $serverKey]); + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/apns') + ->desc('Create APNS Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.create') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderAPNS') + ->label('sdk.description', '/docs/references/messaging/create-provider-apns.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('authKey', '', new Text(0), 'APNS authentication key.') + ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') + ->param('teamId', '', new Text(0), 'APNS team ID.') + ->param('bundleId', '', new Text(0), 'APNS bundle ID.') + ->param('endpoint', '', new Text(0), 'APNS endpoint.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'apns', + 'type' => 'push', + 'credentials' => [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/apns') + ->desc('Update APNS Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.update') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderAPNS') + ->label('sdk.description', '/docs/references/messaging/update-provider-apns.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('authKey', '', new Text(0), 'APNS authentication key.', true) + ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) + ->param('teamId', '', new Text(0), 'APNS team ID.', true) + ->param('bundleId', '', new Text(0), 'APNS bundle ID.', true) + ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); + + if ($providerAttr !== 'apns') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { + // Check if all five variables are present + if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { + $provider->setAttribute('credentials', [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::delete('/v1/messaging/providers/:id') + ->desc('Delete Provider') + ->groups(['api', 'messaging']) + ->label('event', 'messages.providers.[id].delete') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'deleteProvider') + ->label('sdk.description', '/docs/references/messaging/delete-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_NONE) + ->param('id', '', new UID(), 'Provider ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('events') + ->action(function (string $id, Response $response, Database $dbForProject) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $dbForProject->deleteDocument('providers', $provider->getId()); + + $response->noContent(); + }); + App::post('/v1/messaging/messages/email') ->desc('Send an email.') ->groups(['api', 'messaging']) @@ -52,6 +898,7 @@ App::post('/v1/messaging/messages/email') ->label('scope', 'messages.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'sendEmail') ->label('sdk.description', '/docs/references/messaging/send-email.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) @@ -70,7 +917,7 @@ App::post('/v1/messaging/messages/email') $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $message = $dbForProject->createDocument('messages', new Document([ @@ -85,7 +932,7 @@ App::post('/v1/messaging/messages/email') 'deliveryError' => null, 'deliveredTo' => null, 'delivered' => false, - 'search' => null + 'search' => null, ])); $eventsInstance->setParam('messageId', $message->getId()); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index e6d5e8e1b9..cf94135351 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -425,8 +425,7 @@ App::post('/v1/users/:userId/targets') ])); $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId) - ->setParam('targetId', $targetId); + ->setParam('userId', $userId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); @@ -1251,8 +1250,7 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId) - ->setParam('targetId', $targetId); + ->setParam('userId', $userId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1426,7 +1424,6 @@ App::delete('/v1/users/:userId/targets/:targetId') $events ->setParam('userId', $userId) - ->setParam('targetId', $targetId) ->setPayload($response->output($clone, Response::MODEL_USER)); $response->noContent(); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index a3e6817645..d5803f5fbf 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -214,6 +214,7 @@ class Exception extends \Exception /** Provider */ public const PROVIDER_NOT_FOUND = 'provider_not_found'; + public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; protected $type = ''; protected $errors = []; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php new file mode 100644 index 0000000000..83dbf665f1 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php @@ -0,0 +1,21 @@ + Date: Tue, 22 Aug 2023 22:16:09 +0530 Subject: [PATCH 12/72] lint fix --- app/controllers/api/messaging.php | 210 +++++++++++++++--------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 14065f9097..ba1d66b1ed 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -36,17 +36,17 @@ App::get('/v1/messaging/providers') $cursor = reset($cursor); if ($cursor) { - $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ + $providerId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ Query::equal('$id', [$providerId]), Query::limit(1), ])); - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); - } + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); + } - $cursor->setValue($cursorDocument[0]); + $cursor->setValue($cursorDocument[0]); } $filterQueries = Query::groupByType($queries)['filters']; @@ -74,7 +74,7 @@ App::get('/v1/messaging/providers/:id') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $response->dynamic($provider, Response::MODEL_PROVIDER); @@ -137,29 +137,29 @@ App::patch('/v1/messaging/providers/:id/mailgun') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'mailgun') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($apiKey || $domain) { // Check if all five variables are present - if ($apiKey && $domain) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'domain' => $domain - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($apiKey && $domain) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'domain' => $domain + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -221,22 +221,22 @@ App::patch('/v1/messaging/providers/:id/sendgrid') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'sendgrid') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($apiKey) { - $provider->setAttribute('credentials', [ + $provider->setAttribute('credentials', [ 'apiKey' => $apiKey - ]); + ]); } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -304,29 +304,29 @@ App::patch('/v1/messaging/providers/:id/msg91') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'msg91') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($senderId || $authKey) { // Check if all five variables are present - if ($senderId && $authKey) { - $provider->setAttribute('credentials', [ - 'senderId' => $senderId, - 'authKey' => $authKey - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($senderId && $authKey) { + $provider->setAttribute('credentials', [ + 'senderId' => $senderId, + 'authKey' => $authKey + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -391,29 +391,29 @@ App::patch('/v1/messaging/providers/:id/telesign') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'telesign') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($username || $password) { // Check if all five variables are present - if ($username && $password) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'password' => $password - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($username && $password) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'password' => $password + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -478,29 +478,29 @@ App::patch('/v1/messaging/providers/:id/textmagic') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'text-magic') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($username || $apiKey) { // Check if all five variables are present - if ($username && $apiKey) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'apiKey' => $apiKey - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($username && $apiKey) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'apiKey' => $apiKey + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -565,29 +565,29 @@ App::patch('/v1/messaging/providers/:id/twilio') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'twilio') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($accountSid || $authToken) { // Check if all five variables are present - if ($accountSid && $authToken) { - $provider->setAttribute('credentials', [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($accountSid && $authToken) { + $provider->setAttribute('credentials', [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -652,29 +652,29 @@ App::patch('/v1/messaging/providers/:id/vonage') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'vonage') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($apiKey || $apiSecret) { // Check if all five variables are present - if ($apiKey && $apiSecret) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($apiKey && $apiSecret) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -739,20 +739,20 @@ App::patch('/v1/messaging/providers/:id/fcm') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'fcm') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($serverKey) { - $provider->setAttribute('credentials', ['serverKey' => $serverKey]); + $provider->setAttribute('credentials', ['serverKey' => $serverKey]); } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -826,32 +826,32 @@ App::patch('/v1/messaging/providers/:id/apns') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'apns') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { - $provider->setAttribute('name', $name); + $provider->setAttribute('name', $name); } if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { // Check if all five variables are present - if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { - $provider->setAttribute('credentials', [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { + $provider->setAttribute('credentials', [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); @@ -882,7 +882,7 @@ App::delete('/v1/messaging/providers/:id') $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $dbForProject->deleteCachedDocument('providers', $provider->getId()); @@ -917,7 +917,7 @@ App::post('/v1/messaging/messages/email') $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); + throw new Exception(Exception::PROVIDER_NOT_FOUND); } $message = $dbForProject->createDocument('messages', new Document([ From dbbf4522e301d53c32623a80d0d659c123d9613f Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 22 Aug 2023 22:17:32 +0530 Subject: [PATCH 13/72] lint fix --- app/workers/messaging.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 5fba550baa..0ed9853e41 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -47,7 +47,7 @@ class MessagingV1 extends Worker }; } - function push($record): ?PushAdapter + public function push($record): ?PushAdapter { $credentials = $record->getAttribute('credentials'); return match ($record->getAttribute('provider')) { @@ -106,7 +106,7 @@ class MessagingV1 extends Worker // Send the message using respective adapter } - function shutdown(): void + public function shutdown(): void { } } From c225563d776ef5da3ae641b964cef15619d5fe17 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 23 Aug 2023 15:31:29 +0530 Subject: [PATCH 14/72] adds test for provider controllers --- app/config/roles.php | 8 + app/controllers/api/messaging.php | 58 +++--- phpunit.xml | 1 + tests/e2e/Scopes/ProjectCustom.php | 4 + .../Messaging/MessagingServerTest.php | 187 ++++++++++++++++++ 5 files changed, 224 insertions(+), 34 deletions(-) create mode 100644 tests/e2e/Services/Messaging/MessagingServerTest.php diff --git a/app/config/roles.php b/app/config/roles.php index a95b34d820..4bc85f7a28 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -22,6 +22,10 @@ $member = [ 'execution.write', 'targets.read', 'targets.write', + 'providers.write', + 'providers.read', + 'messages.write', + 'messages.read' ]; $admins = [ @@ -57,6 +61,10 @@ $admins = [ 'migrations.write', 'targets.read', 'targets.write', + 'providers.write', + 'providers.read', + 'messages.write', + 'messages.read' ]; return [ diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index ba1d66b1ed..1ff95fbeea 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -70,7 +70,7 @@ App::get('/v1/messaging/providers/:id') ->param('id', null, new UID(), 'Provider ID.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, Response $response, Database $dbForProject) { + ->action(function (string $id, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -86,7 +86,7 @@ App::get('/v1/messaging/providers/:id') App::post('/v1/messaging/providers/mailgun') ->desc('Create Mailgun Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -118,7 +118,7 @@ App::post('/v1/messaging/providers/mailgun') App::patch('/v1/messaging/providers/:id/mailgun') ->desc('Update Mailgun Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -166,14 +166,13 @@ App::patch('/v1/messaging/providers/:id/mailgun') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/sendgrid') ->desc('Create Sendgrid Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -203,7 +202,7 @@ App::post('/v1/messaging/providers/sendgrid') App::patch('/v1/messaging/providers/:id/sendgrid') ->desc('Update Sendgrid Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -243,7 +242,6 @@ App::patch('/v1/messaging/providers/:id/sendgrid') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -253,7 +251,7 @@ App::patch('/v1/messaging/providers/:id/sendgrid') App::post('/v1/messaging/providers/msg91') ->desc('Create Msg91 Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -285,7 +283,7 @@ App::post('/v1/messaging/providers/msg91') App::patch('/v1/messaging/providers/:id/msg91') ->desc('Update Msg91 Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -333,14 +331,13 @@ App::patch('/v1/messaging/providers/:id/msg91') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/telesign') ->desc('Create Telesign Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -372,7 +369,7 @@ App::post('/v1/messaging/providers/telesign') App::patch('/v1/messaging/providers/:id/telesign') ->desc('Update Telesign Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -420,14 +417,13 @@ App::patch('/v1/messaging/providers/:id/telesign') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/textmagic') ->desc('Create Textmagic Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -459,7 +455,7 @@ App::post('/v1/messaging/providers/textmagic') App::patch('/v1/messaging/providers/:id/textmagic') ->desc('Update Textmagic Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -507,14 +503,13 @@ App::patch('/v1/messaging/providers/:id/textmagic') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/twilio') ->desc('Create Twilio Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -546,7 +541,7 @@ App::post('/v1/messaging/providers/twilio') App::patch('/v1/messaging/providers/:id/twilio') ->desc('Update Twilio Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -594,14 +589,13 @@ App::patch('/v1/messaging/providers/:id/twilio') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/vonage') ->desc('Create Vonage Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -633,7 +627,7 @@ App::post('/v1/messaging/providers/vonage') App::patch('/v1/messaging/providers/:id/vonage') ->desc('Update Vonage Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -681,7 +675,6 @@ App::patch('/v1/messaging/providers/:id/vonage') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -691,7 +684,7 @@ App::patch('/v1/messaging/providers/:id/vonage') App::post('/v1/messaging/providers/fcm') ->desc('Create FCM Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -721,7 +714,7 @@ App::post('/v1/messaging/providers/fcm') App::patch('/v1/messaging/providers/:id/fcm') ->desc('Update FCM Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -759,14 +752,13 @@ App::patch('/v1/messaging/providers/:id/fcm') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/apns') ->desc('Create APNS Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.create') + ->label('audits.event', 'messages.providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -804,7 +796,7 @@ App::post('/v1/messaging/providers/apns') App::patch('/v1/messaging/providers/:id/apns') ->desc('Update APNS Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.update') + ->label('audits.event', 'messages.providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -858,27 +850,25 @@ App::patch('/v1/messaging/providers/:id/apns') $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); App::delete('/v1/messaging/providers/:id') ->desc('Delete Provider') ->groups(['api', 'messaging']) - ->label('event', 'messages.providers.[id].delete') + ->label('audits.event', 'messages.providers.delete') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'deleteProvider') ->label('sdk.description', '/docs/references/messaging/delete-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) ->param('id', '', new UID(), 'Provider ID.') - ->inject('response') ->inject('dbForProject') - ->inject('events') - ->action(function (string $id, Response $response, Database $dbForProject) { + ->inject('response') + ->action(function (string $id, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -894,7 +884,7 @@ App::delete('/v1/messaging/providers/:id') App::post('/v1/messaging/messages/email') ->desc('Send an email.') ->groups(['api', 'messaging']) - ->label('event', 'messages.create') + ->label('audits.event', 'messages.create') ->label('scope', 'messages.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') diff --git a/phpunit.xml b/phpunit.xml index f83f9f0fae..cffe166336 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -32,6 +32,7 @@ ./tests/e2e/Services/Teams ./tests/e2e/Services/Users ./tests/e2e/Services/Webhooks + ./tests/e2e/Services/Messaging ./tests/e2e/Services/Functions/FunctionsBase.php ./tests/e2e/Services/Functions/FunctionsCustomServerTest.php ./tests/e2e/Services/Functions/FunctionsCustomClientTest.php diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 1bd4de501c..ee41129fde 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -81,6 +81,10 @@ trait ProjectCustom 'locale.read', 'avatars.read', 'health.read', + 'providers.read', + 'providers.write', + 'messages.read', + 'messages.write', ], ]); diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php new file mode 100644 index 0000000000..2547c8a756 --- /dev/null +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -0,0 +1,187 @@ + [ + 'name' => 'Sengrid1', + 'apiKey' => 'my-apikey', + ], + 'mailgun' => [ + 'name' => 'Mailgun1', + 'apiKey' => 'my-apikey', + 'domain' => 'my-domain', + ], + 'twilio' => [ + 'name' => 'Twilio1', + 'accountSid' => 'my-accountSid', + 'authToken' => 'my-authToken', + ], + 'telesign' => [ + 'name' => 'Telesign1', + 'username' => 'my-username', + 'password' => 'my-password', + ], + 'textmagic' => [ + 'name' => 'Textmagic1', + 'username' => 'my-username', + 'apiKey' => 'my-apikey', + ], + 'msg91' => [ + 'name' => 'Ms91-1', + 'senderId' => 'my-senderid', + 'authKey' => 'my-authkey', + ], + 'vonage' => [ + 'name' => 'Vonage1', + 'apiKey' => 'my-apikey', + 'apiSecret' => 'my-apisecret', + ], + 'fcm' => [ + 'name' => 'FCM1', + 'serverKey' => 'my-serverkey', + ], + 'apns' => [ + 'name' => 'APNS1', + 'authKey' => 'my-authkey', + 'authKeyId' => 'my-authkeyid', + 'teamId' => 'my-teamid', + 'bundleId' => 'my-bundleid', + 'endpoint' => 'my-endpoint', + ], + ]; + $providers = []; + + foreach (\array_keys($providersParams) as $key) { + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/'.$key, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $providersParams[$key]); + \array_push($providers, $response['body']); + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); + } + + return $providers; + } + + /** + * @depends testCreateProviders + */ + public function testUpdateProviders(array $providers): array + { + $providersParams = [ + 'sendgrid' => [ + 'name' => 'Sengrid2', + 'apiKey' => 'my-apikey', + ], + 'mailgun' => [ + 'name' => 'Mailgun2', + 'apiKey' => 'my-apikey', + 'domain' => 'my-domain', + ], + 'twilio' => [ + 'name' => 'Twilio2', + 'accountSid' => 'my-accountSid', + 'authToken' => 'my-authToken', + ], + 'telesign' => [ + 'name' => 'Telesign2', + 'username' => 'my-username', + 'password' => 'my-password', + ], + 'textmagic' => [ + 'name' => 'Textmagic2', + 'username' => 'my-username', + 'apiKey' => 'my-apikey', + ], + 'msg91' => [ + 'name' => 'Ms91-2', + 'senderId' => 'my-senderid', + 'authKey' => 'my-authkey', + ], + 'vonage' => [ + 'name' => 'Vonage2', + 'apiKey' => 'my-apikey', + 'apiSecret' => 'my-apisecret', + ], + 'fcm' => [ + 'name' => 'FCM2', + 'serverKey' => 'my-serverkey', + ], + 'apns' => [ + 'name' => 'APNS2', + 'authKey' => 'my-authkey', + 'authKeyId' => 'my-authkeyid', + 'teamId' => 'my-teamid', + 'bundleId' => 'my-bundleid', + 'endpoint' => 'my-endpoint', + ], + ]; + foreach (\array_keys($providersParams) as $index => $key) { + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/'. $providers[$index]['$id'] . '/' . $key, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $providersParams[$key]); + $providers[$index] = $response['body']; + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); + } + + return $providers; + } + + /** + * @depends testUpdateProviders + */ + public function testListProviders(array $providers) { + $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(\count($providers), $response['body']['total']); + } + + /** + * @depends testUpdateProviders + */ + public function testGetProvider(array $providers) { + $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/' .$providers[0]['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($providers[0]['name'], $response['body']['name']); + } + + /** + * @depends testUpdateProviders + */ + public function testDeleteProvider(array $providers) { + foreach ($providers as $provider) { + $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/'. $provider['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertEquals(204, $response['headers']['status-code']); + } + } +} From 55d00d9afaac9cb40662076c4e9423db72cb3e54 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 23 Aug 2023 15:36:12 +0530 Subject: [PATCH 15/72] lint fix --- .../Services/Messaging/MessagingServerTest.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 2547c8a756..7b93ab29ac 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -65,7 +65,7 @@ class MessagingServerTest extends Scope $providers = []; foreach (\array_keys($providersParams) as $key) { - $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/'.$key, [ + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -132,7 +132,7 @@ class MessagingServerTest extends Scope ], ]; foreach (\array_keys($providersParams) as $index => $key) { - $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/'. $providers[$index]['$id'] . '/' . $key, [ + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $providers[$index]['$id'] . '/' . $key, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -148,7 +148,8 @@ class MessagingServerTest extends Scope /** * @depends testUpdateProviders */ - public function testListProviders(array $providers) { + public function testListProviders(array $providers) + { $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -161,8 +162,9 @@ class MessagingServerTest extends Scope /** * @depends testUpdateProviders */ - public function testGetProvider(array $providers) { - $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/' .$providers[0]['$id'], [ + public function testGetProvider(array $providers) + { + $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $providers[0]['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -174,9 +176,10 @@ class MessagingServerTest extends Scope /** * @depends testUpdateProviders */ - public function testDeleteProvider(array $providers) { + public function testDeleteProvider(array $providers) + { foreach ($providers as $provider) { - $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/'. $provider['$id'], [ + $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/' . $provider['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], From 3e7805afe1a7ad48d0628516fe5c640fa532909d Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 23 Aug 2023 08:49:32 -0400 Subject: [PATCH 16/72] Updates deps Adds message builders to messaging worker Adds Makefile to .gitignore ;) --- .gitignore | 1 + app/workers/messaging.php | 63 +++++++++++++++++++++++++++++++++++---- composer.lock | 13 ++++---- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 3151de5adb..ac88830b49 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ debug/ app/sdks dev/yasd_init.php .phpunit.result.cache +Makefile diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 0ed9853e41..e958d5ece4 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -97,16 +97,67 @@ class MessagingV1 extends Worker // call function passing needed credentials returns required provider. $messageId = $this->args['messageId']; - $message = - $this - ->getConsoleDB() - ->getDocument('messages', $messageId); + $messageRecord = + $this + ->getConsoleDB() + ->getDocument('messages', $messageId); - // Contrust Message Object according to each provider type. - // Send the message using respective adapter + $message = match ($providerRecord->getAttribute('type')) { + 'sms' => $this->buildSMSMessage($messageRecord->getArrayCopy()), + 'push' => $this->buildPushMessage($messageRecord->getArrayCopy()), + 'email' => $this->buildEmailMessage($messageRecord->getArrayCopy()), + default => null + }; + + + $provider->send($message); } public function shutdown(): void { } + + private function buildEmailMessage($data): array + { + $from = $data['from']; + $to = $data['to']; + $subject = $data['subject']; + $body = $data['content']; + + return [ + 'from' => $from, + 'to' => $to, + 'subject' => $subject, + 'body' => $body, + ]; + return $message; + } + + private function buildSMSMessage($data): array + { + $from = $data['from']; + $to = $data['to']; + $body = $data['content']; + + return [ + 'from' => $from, + 'to' => $to, + 'body' => $body + ]; + } + + private function buildPushMessage($data): array + { + $to = $data['to']; + $title = $data['title']; + $body = $data['body']; + $data = $data['data']; + + return [ + 'to' => $to, + 'title' => $title, + 'body' => $body, + 'data' => $data + ]; + } } diff --git a/composer.lock b/composer.lock index 55e84a6e74..f2b39d8414 100644 --- a/composer.lock +++ b/composer.lock @@ -1557,19 +1557,20 @@ }, { "name": "utopia-php/database", - "version": "0.42.2", + "version": "0.42.3", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "bc5ceb30c85fb685b0b5704d2f74886d813ebd41" + "reference": "ab0e2f8ad46884f69b354cd8ee84a1a75fee26d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/bc5ceb30c85fb685b0b5704d2f74886d813ebd41", - "reference": "bc5ceb30c85fb685b0b5704d2f74886d813ebd41", + "url": "https://api.github.com/repos/utopia-php/database/zipball/ab0e2f8ad46884f69b354cd8ee84a1a75fee26d1", + "reference": "ab0e2f8ad46884f69b354cd8ee84a1a75fee26d1", "shasum": "" }, "require": { + "ext-mbstring": "*", "ext-pdo": "*", "php": ">=8.0", "utopia-php/cache": "0.8.*", @@ -1607,9 +1608,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.42.2" + "source": "https://github.com/utopia-php/database/tree/0.42.3" }, - "time": "2023-08-17T19:04:37+00:00" + "time": "2023-08-22T02:15:28+00:00" }, { "name": "utopia-php/domains", From eba91ae55a2f446e65bac1b15181b9a12c12941c Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 23 Aug 2023 12:22:04 -0400 Subject: [PATCH 17/72] Stubbing in tests and message builder --- app/workers/messaging.php | 1 - tests/e2e/Services/Messaging/MessagingServerTest.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/messaging.php b/app/workers/messaging.php index e958d5ece4..84af6fa802 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -130,7 +130,6 @@ class MessagingV1 extends Worker 'subject' => $subject, 'body' => $body, ]; - return $message; } private function buildSMSMessage($data): array diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 7b93ab29ac..9bc9f93caf 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -187,4 +187,5 @@ class MessagingServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } } + } From bf5f0a841921920e3a2cca09875fa9946d73ce89 Mon Sep 17 00:00:00 2001 From: wess Date: Wed, 23 Aug 2023 13:12:43 -0400 Subject: [PATCH 18/72] Pint linter ran --- app/cli.php | 31 +- app/config/authProviders.php | 14 +- app/config/avatars/browsers.php | 29 +- app/config/avatars/credit-cards.php | 34 +- app/config/avatars/flags.php | 388 +++--- app/config/avatars/os.php | 6 +- app/config/collections.php | 48 +- app/config/errors.php | 8 +- app/config/events.php | 66 +- app/config/locale/codes.php | 525 ++++---- app/config/locale/languages.php | 1106 ++++++++--------- app/config/locale/templates.php | 4 +- app/config/messagingProviders.php | 586 ++++----- app/config/platforms.php | 44 +- app/config/regions.php | 2 +- app/config/roles.php | 4 +- app/config/runtimes.php | 2 +- app/config/scopes.php | 4 +- app/config/services.php | 6 +- app/config/usage.php | 40 +- app/config/variables.php | 196 +-- app/controllers/api/account.php | 527 ++++---- app/controllers/api/avatars.php | 169 ++- app/controllers/api/console.php | 3 - app/controllers/api/databases.php | 642 +++++----- app/controllers/api/functions.php | 207 ++- app/controllers/api/graphql.php | 23 +- app/controllers/api/health.php | 98 +- app/controllers/api/locale.php | 27 +- app/controllers/api/messaging.php | 788 ++++++------ app/controllers/api/migrations.php | 40 +- app/controllers/api/project.php | 28 +- app/controllers/api/projects.php | 178 +-- app/controllers/api/storage.php | 306 +++-- app/controllers/api/teams.php | 175 ++- app/controllers/api/users.php | 139 +-- app/controllers/general.php | 157 ++- app/controllers/mock.php | 69 +- app/controllers/shared/api.php | 107 +- app/controllers/shared/api/auth.php | 3 +- app/controllers/web/console.php | 24 +- app/controllers/web/home.php | 4 +- app/http.php | 76 +- app/init.php | 303 ++--- app/preload.php | 40 +- app/realtime.php | 149 ++- app/worker.php | 40 +- app/workers/audits.php | 6 +- app/workers/builds.php | 39 +- app/workers/certificates.php | 144 +-- app/workers/databases.php | 104 +- app/workers/deletes.php | 275 ++-- app/workers/functions.php | 40 +- app/workers/mails.php | 18 +- app/workers/messaging.php | 37 +- app/workers/migrations.php | 4 +- app/workers/usage.php | 92 +- app/workers/webhooks.php | 30 +- src/Appwrite/Auth/Auth.php | 117 +- src/Appwrite/Auth/Hash.php | 25 +- src/Appwrite/Auth/Hash/Argon2.php | 10 +- src/Appwrite/Auth/Hash/Bcrypt.php | 12 +- src/Appwrite/Auth/Hash/Md5.php | 10 +- src/Appwrite/Auth/Hash/Phpass.php | 61 +- src/Appwrite/Auth/Hash/Scrypt.php | 12 +- src/Appwrite/Auth/Hash/Scryptmodified.php | 14 +- src/Appwrite/Auth/Hash/Sha.php | 12 +- src/Appwrite/Auth/OAuth2.php | 56 +- src/Appwrite/Auth/OAuth2/Amazon.php | 40 +- src/Appwrite/Auth/OAuth2/Apple.php | 47 +- src/Appwrite/Auth/OAuth2/Auth0.php | 41 +- src/Appwrite/Auth/OAuth2/Authentik.php | 47 +- src/Appwrite/Auth/OAuth2/Autodesk.php | 29 +- src/Appwrite/Auth/OAuth2/Bitbucket.php | 32 +- src/Appwrite/Auth/OAuth2/Bitly.php | 57 +- src/Appwrite/Auth/OAuth2/Box.php | 53 +- src/Appwrite/Auth/OAuth2/Dailymotion.php | 50 +- src/Appwrite/Auth/OAuth2/Discord.php | 39 +- src/Appwrite/Auth/OAuth2/Disqus.php | 36 +- src/Appwrite/Auth/OAuth2/Dropbox.php | 31 +- src/Appwrite/Auth/OAuth2/Etsy.php | 33 +- src/Appwrite/Auth/OAuth2/Exception.php | 6 +- src/Appwrite/Auth/OAuth2/Facebook.php | 39 +- src/Appwrite/Auth/OAuth2/Firebase.php | 75 +- src/Appwrite/Auth/OAuth2/Github.php | 40 +- src/Appwrite/Auth/OAuth2/Gitlab.php | 40 +- src/Appwrite/Auth/OAuth2/Google.php | 37 +- src/Appwrite/Auth/OAuth2/Linkedin.php | 33 +- src/Appwrite/Auth/OAuth2/Microsoft.php | 40 +- src/Appwrite/Auth/OAuth2/Mock.php | 38 +- src/Appwrite/Auth/OAuth2/Notion.php | 43 +- src/Appwrite/Auth/OAuth2/Oidc.php | 82 +- src/Appwrite/Auth/OAuth2/Okta.php | 41 +- src/Appwrite/Auth/OAuth2/Paypal.php | 41 +- src/Appwrite/Auth/OAuth2/PaypalSandbox.php | 2 - src/Appwrite/Auth/OAuth2/Podio.php | 41 +- src/Appwrite/Auth/OAuth2/Salesforce.php | 42 +- src/Appwrite/Auth/OAuth2/Slack.php | 39 +- src/Appwrite/Auth/OAuth2/Spotify.php | 47 +- src/Appwrite/Auth/OAuth2/Stripe.php | 37 +- src/Appwrite/Auth/OAuth2/Tradeshift.php | 52 +- src/Appwrite/Auth/OAuth2/TradeshiftBox.php | 2 - src/Appwrite/Auth/OAuth2/Twitch.php | 53 +- src/Appwrite/Auth/OAuth2/WordPress.php | 31 +- src/Appwrite/Auth/OAuth2/Yahoo.php | 49 +- src/Appwrite/Auth/OAuth2/Yammer.php | 37 +- src/Appwrite/Auth/OAuth2/Yandex.php | 43 +- src/Appwrite/Auth/OAuth2/Zoom.php | 39 +- src/Appwrite/Auth/Validator/Password.php | 5 +- .../Auth/Validator/PasswordDictionary.php | 7 +- .../Auth/Validator/PasswordHistory.php | 6 +- src/Appwrite/Auth/Validator/PersonalData.php | 7 +- src/Appwrite/Auth/Validator/Phone.php | 5 +- src/Appwrite/Detector/Detector.php | 8 +- src/Appwrite/Docker/Compose.php | 4 +- src/Appwrite/Docker/Compose/Service.php | 5 +- src/Appwrite/Docker/Env.php | 14 +- src/Appwrite/Event/Audit.php | 12 +- src/Appwrite/Event/Build.php | 11 +- src/Appwrite/Event/Certificate.php | 8 +- src/Appwrite/Event/Database.php | 17 +- src/Appwrite/Event/Delete.php | 25 +- src/Appwrite/Event/Event.php | 78 +- src/Appwrite/Event/Func.php | 20 +- src/Appwrite/Event/Mail.php | 37 +- src/Appwrite/Event/Migration.php | 14 +- src/Appwrite/Event/Phone.php | 8 +- src/Appwrite/Event/Usage.php | 13 +- src/Appwrite/Event/Validator/Event.php | 24 +- src/Appwrite/Extend/Exception.php | 371 ++++-- src/Appwrite/GraphQL/Promises/Adapter.php | 21 +- src/Appwrite/GraphQL/Resolvers.php | 129 +- src/Appwrite/GraphQL/Schema.php | 68 +- src/Appwrite/GraphQL/Types.php | 3 + src/Appwrite/GraphQL/Types/Assoc.php | 8 +- src/Appwrite/GraphQL/Types/InputFile.php | 3 +- src/Appwrite/GraphQL/Types/Json.php | 4 +- src/Appwrite/GraphQL/Types/Mapper.php | 49 +- src/Appwrite/GraphQL/Types/Registry.php | 8 +- src/Appwrite/Messaging/Adapter.php | 2 + src/Appwrite/Messaging/Adapter/Realtime.php | 84 +- src/Appwrite/Migration/Migration.php | 80 +- src/Appwrite/Migration/Version/V15.php | 47 +- src/Appwrite/Migration/Version/V16.php | 14 +- src/Appwrite/Migration/Version/V17.php | 12 +- src/Appwrite/Migration/Version/V18.php | 6 +- src/Appwrite/Migration/Version/V19.php | 11 +- src/Appwrite/Network/Validator/CNAME.php | 9 +- src/Appwrite/Network/Validator/Email.php | 6 +- src/Appwrite/Network/Validator/Origin.php | 39 +- src/Appwrite/OpenSSL/OpenSSL.php | 26 +- src/Appwrite/Platform/Services/Tasks.php | 20 +- src/Appwrite/Platform/Tasks/CalcTierStats.php | 54 +- .../Platform/Tasks/CalcUsersStats.php | 27 +- .../Platform/Tasks/ClearCardCache.php | 14 +- src/Appwrite/Platform/Tasks/Doctor.php | 91 +- src/Appwrite/Platform/Tasks/Hamster.php | 99 +- src/Appwrite/Platform/Tasks/Install.php | 68 +- src/Appwrite/Platform/Tasks/Maintenance.php | 18 +- src/Appwrite/Platform/Tasks/Migrate.php | 21 +- .../Tasks/PatchCreateMissingSchedules.php | 16 +- .../Tasks/PatchDeleteProjectCollections.php | 22 +- .../PatchDeleteScheduleUpdatedAtAttribute.php | 8 +- src/Appwrite/Platform/Tasks/SDKs.php | 86 +- src/Appwrite/Platform/Tasks/SSL.php | 6 +- src/Appwrite/Platform/Tasks/Schedule.php | 37 +- src/Appwrite/Platform/Tasks/Specs.php | 50 +- src/Appwrite/Platform/Tasks/Vars.php | 4 +- src/Appwrite/Platform/Tasks/VolumeSync.php | 14 +- src/Appwrite/Promises/Promise.php | 35 +- src/Appwrite/Promises/Swoole.php | 4 +- src/Appwrite/Resque/Worker.php | 84 +- src/Appwrite/Specification/Format.php | 31 +- .../Specification/Format/OpenAPI3.php | 92 +- .../Specification/Format/Swagger2.php | 82 +- src/Appwrite/Task/Validator/Cron.php | 5 +- src/Appwrite/Template/Template.php | 37 +- src/Appwrite/URL/URL.php | 34 +- .../Utopia/Database/Validator/CustomId.php | 2 - .../Utopia/Database/Validator/ProjectId.php | 1 - .../Database/Validator/Queries/Attributes.php | 5 +- .../Database/Validator/Queries/Base.php | 20 +- .../Database/Validator/Queries/Buckets.php | 3 +- .../Validator/Queries/Collections.php | 3 +- .../Database/Validator/Queries/Databases.php | 3 +- .../Validator/Queries/Deployments.php | 1 - .../Database/Validator/Queries/Executions.php | 3 +- .../Database/Validator/Queries/Files.php | 3 +- .../Database/Validator/Queries/Functions.php | 3 +- .../Database/Validator/Queries/Identities.php | 1 - .../Database/Validator/Queries/Indexes.php | 1 - .../Validator/Queries/Memberships.php | 3 +- .../Database/Validator/Queries/Migrations.php | 3 +- .../Database/Validator/Queries/Projects.php | 5 +- .../Database/Validator/Queries/Providers.php | 1 - .../Database/Validator/Queries/Teams.php | 3 +- .../Database/Validator/Queries/Users.php | 3 +- .../Database/Validator/Queries/Variables.php | 5 +- src/Appwrite/Utopia/Request.php | 11 +- src/Appwrite/Utopia/Request/Filter.php | 5 +- src/Appwrite/Utopia/Request/Filters/V12.php | 45 +- src/Appwrite/Utopia/Request/Filters/V13.php | 16 +- src/Appwrite/Utopia/Request/Filters/V14.php | 12 +- src/Appwrite/Utopia/Request/Filters/V15.php | 25 +- src/Appwrite/Utopia/Response.php | 258 ++-- src/Appwrite/Utopia/Response/Filter.php | 5 +- src/Appwrite/Utopia/Response/Filters/V11.php | 35 +- src/Appwrite/Utopia/Response/Filters/V12.php | 12 + src/Appwrite/Utopia/Response/Filters/V13.php | 3 + src/Appwrite/Utopia/Response/Filters/V15.php | 18 +- src/Appwrite/Utopia/Response/Model.php | 16 +- .../Utopia/Response/Model/AlgoArgon2.php | 3 +- .../Utopia/Response/Model/AlgoScrypt.php | 3 +- .../Response/Model/AlgoScryptModified.php | 3 +- .../Utopia/Response/Model/Attribute.php | 3 +- .../Response/Model/AttributeBoolean.php | 7 +- .../Response/Model/AttributeDatetime.php | 5 +- .../Utopia/Response/Model/AttributeEmail.php | 5 +- .../Utopia/Response/Model/AttributeEnum.php | 5 +- .../Utopia/Response/Model/AttributeFloat.php | 3 +- .../Utopia/Response/Model/AttributeIP.php | 5 +- .../Response/Model/AttributeInteger.php | 4 +- .../Utopia/Response/Model/AttributeList.php | 7 +- .../Response/Model/AttributeRelationship.php | 6 +- .../Utopia/Response/Model/AttributeString.php | 3 +- .../Utopia/Response/Model/AttributeURL.php | 5 +- .../Utopia/Response/Model/AuthProvider.php | 3 +- .../Utopia/Response/Model/BaseList.php | 20 +- src/Appwrite/Utopia/Response/Model/Bucket.php | 9 +- src/Appwrite/Utopia/Response/Model/Build.php | 3 +- .../Utopia/Response/Model/Collection.php | 7 +- .../Utopia/Response/Model/Continent.php | 3 +- .../Utopia/Response/Model/Country.php | 3 +- .../Utopia/Response/Model/Currency.php | 3 +- .../Utopia/Response/Model/Database.php | 3 +- .../Utopia/Response/Model/Deployment.php | 3 +- src/Appwrite/Utopia/Response/Model/Domain.php | 3 +- src/Appwrite/Utopia/Response/Model/Error.php | 3 +- .../Utopia/Response/Model/ErrorDev.php | 3 +- .../Utopia/Response/Model/Execution.php | 3 +- src/Appwrite/Utopia/Response/Model/File.php | 3 +- src/Appwrite/Utopia/Response/Model/Func.php | 7 +- .../Utopia/Response/Model/HealthAntivirus.php | 3 +- .../Utopia/Response/Model/HealthQueue.php | 3 +- .../Utopia/Response/Model/HealthStatus.php | 3 +- .../Utopia/Response/Model/HealthTime.php | 3 +- .../Utopia/Response/Model/HealthVersion.php | 3 +- .../Utopia/Response/Model/Identity.php | 3 +- src/Appwrite/Utopia/Response/Model/Index.php | 3 +- src/Appwrite/Utopia/Response/Model/JWT.php | 3 +- src/Appwrite/Utopia/Response/Model/Key.php | 9 +- .../Utopia/Response/Model/Language.php | 3 +- src/Appwrite/Utopia/Response/Model/Locale.php | 3 +- .../Utopia/Response/Model/LocaleCode.php | 3 +- src/Appwrite/Utopia/Response/Model/Log.php | 3 +- .../Utopia/Response/Model/Membership.php | 3 +- src/Appwrite/Utopia/Response/Model/Metric.php | 2 +- .../Utopia/Response/Model/Migration.php | 5 +- src/Appwrite/Utopia/Response/Model/Mock.php | 3 +- src/Appwrite/Utopia/Response/Model/Phone.php | 3 +- .../Utopia/Response/Model/Platform.php | 3 +- .../Utopia/Response/Model/Project.php | 37 +- .../Utopia/Response/Model/Runtime.php | 5 +- .../Utopia/Response/Model/Session.php | 3 +- src/Appwrite/Utopia/Response/Model/Team.php | 4 +- .../Utopia/Response/Model/Template.php | 3 +- .../Utopia/Response/Model/TemplateEmail.php | 3 +- .../Utopia/Response/Model/TemplateSMS.php | 1 + src/Appwrite/Utopia/Response/Model/Token.php | 3 +- .../Utopia/Response/Model/UsageBuckets.php | 7 +- .../Utopia/Response/Model/UsageCollection.php | 5 +- .../Utopia/Response/Model/UsageDatabase.php | 7 +- .../Utopia/Response/Model/UsageDatabases.php | 9 +- .../Utopia/Response/Model/UsageFunction.php | 17 +- .../Utopia/Response/Model/UsageFunctions.php | 19 +- .../Utopia/Response/Model/UsageProject.php | 19 +- .../Utopia/Response/Model/UsageStorage.php | 9 +- .../Utopia/Response/Model/UsageUsers.php | 7 +- src/Appwrite/Utopia/Response/Model/User.php | 6 +- .../Utopia/Response/Model/Variable.php | 3 +- .../Utopia/Response/Model/Webhook.php | 3 +- src/Appwrite/Utopia/View.php | 3 +- src/Executor/Executor.php | 104 +- tests/e2e/Client.php | 66 +- tests/e2e/General/AbuseTest.php | 42 +- tests/e2e/General/HTTPTest.php | 8 +- tests/e2e/General/UsageTest.php | 111 +- tests/e2e/Scopes/ProjectCustom.php | 23 +- tests/e2e/Scopes/Scope.php | 11 +- tests/e2e/Scopes/SideClient.php | 2 +- tests/e2e/Scopes/SideConsole.php | 4 +- tests/e2e/Scopes/SideServer.php | 2 +- tests/e2e/Services/Account/AccountBase.php | 197 ++- .../Account/AccountConsoleClientTest.php | 14 +- .../Account/AccountCustomClientTest.php | 141 +-- .../Account/AccountCustomServerTest.php | 2 +- tests/e2e/Services/Avatars/AvatarsBase.php | 17 +- .../Avatars/AvatarsConsoleClientTest.php | 2 +- .../Avatars/AvatarsCustomClientTest.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 900 +++++++------- .../Databases/DatabasesConsoleClientTest.php | 84 +- .../Databases/DatabasesCustomClientTest.php | 269 ++-- .../Databases/DatabasesCustomServerTest.php | 1088 ++++++++-------- .../DatabasesPermissionsGuestTest.php | 48 +- .../DatabasesPermissionsMemberTest.php | 40 +- .../Databases/DatabasesPermissionsScope.php | 15 +- .../DatabasesPermissionsTeamTest.php | 27 +- .../e2e/Services/Functions/FunctionsBase.php | 3 +- .../Functions/FunctionsConsoleClientTest.php | 125 +- .../Functions/FunctionsCustomClientTest.php | 105 +- .../Functions/FunctionsCustomServerTest.php | 231 ++-- tests/e2e/Services/GraphQL/AbuseTest.php | 8 +- tests/e2e/Services/GraphQL/AccountTest.php | 36 +- tests/e2e/Services/GraphQL/AuthTest.php | 49 +- tests/e2e/Services/GraphQL/Base.php | 155 ++- tests/e2e/Services/GraphQL/BatchTest.php | 39 +- .../e2e/Services/GraphQL/ContentTypeTest.php | 8 +- .../Services/GraphQL/DatabaseClientTest.php | 22 +- .../Services/GraphQL/DatabaseServerTest.php | 137 +- .../Services/GraphQL/FunctionsClientTest.php | 26 +- .../Services/GraphQL/FunctionsServerTest.php | 54 +- .../e2e/Services/GraphQL/LocalizationTest.php | 2 +- tests/e2e/Services/GraphQL/ScopeTest.php | 5 +- .../Services/GraphQL/StorageClientTest.php | 36 +- .../Services/GraphQL/StorageServerTest.php | 49 +- .../e2e/Services/GraphQL/TeamsServerTest.php | 8 +- tests/e2e/Services/GraphQL/UsersTest.php | 39 +- tests/e2e/Services/Health/HealthBase.php | 2 - .../Health/HealthCustomServerTest.php | 3 +- tests/e2e/Services/Locale/LocaleBase.php | 16 +- .../Locale/LocaleConsoleClientTest.php | 2 +- .../Locale/LocaleCustomClientTest.php | 2 +- .../Locale/LocaleCustomServerTest.php | 1 - .../Messaging/MessagingServerTest.php | 9 +- tests/e2e/Services/Projects/ProjectsBase.php | 2 - .../Projects/ProjectsConsoleClientTest.php | 487 ++++---- .../Projects/ProjectsCustomClientTest.php | 3 +- .../Projects/ProjectsCustomServerTest.php | 1 - tests/e2e/Services/Realtime/RealtimeBase.php | 12 +- .../Realtime/RealtimeConsoleClientTest.php | 53 +- .../Realtime/RealtimeCustomClientTest.php | 331 +++-- tests/e2e/Services/Storage/StorageBase.php | 161 ++- .../Storage/StorageConsoleClientTest.php | 29 +- .../Storage/StorageCustomClientTest.php | 419 ++++--- .../Storage/StorageCustomServerTest.php | 46 +- .../Storage/StoragePermissionsScope.php | 16 +- tests/e2e/Services/Teams/TeamsBase.php | 47 +- tests/e2e/Services/Teams/TeamsBaseClient.php | 155 ++- tests/e2e/Services/Teams/TeamsBaseServer.php | 52 +- .../Services/Teams/TeamsConsoleClientTest.php | 34 +- .../Services/Teams/TeamsCustomClientTest.php | 2 +- .../Services/Teams/TeamsCustomServerTest.php | 1 - tests/e2e/Services/Users/UsersBase.php | 134 +- .../Services/Users/UsersConsoleClientTest.php | 9 +- .../Services/Users/UsersCustomServerTest.php | 1 - tests/e2e/Services/Webhooks/WebhooksBase.php | 136 +- .../Webhooks/WebhooksCustomClientTest.php | 102 +- .../Webhooks/WebhooksCustomServerTest.php | 77 +- tests/extensions/Retryable.php | 13 +- tests/extensions/TestHook.php | 2 +- tests/resources/functions/php-fn/index.php | 2 +- tests/resources/functions/php-large/index.php | 2 +- tests/resources/functions/php/index.php | 2 +- tests/unit/Auth/AuthTest.php | 62 +- .../Auth/Validator/PasswordDictionaryTest.php | 1 - tests/unit/Docker/ComposeTest.php | 2 +- tests/unit/Docker/EnvTest.php | 6 +- tests/unit/Event/EventTest.php | 12 +- tests/unit/General/CollectionsTest.php | 2 +- .../unit/Messaging/MessagingChannelsTest.php | 53 +- tests/unit/Messaging/MessagingGuestTest.php | 4 +- tests/unit/Messaging/MessagingTest.php | 28 +- tests/unit/Migration/MigrationTest.php | 50 +- tests/unit/Network/Validators/EmailTest.php | 5 +- tests/unit/Template/TemplateTest.php | 5 +- tests/unit/Usage/StatsTest.php | 23 +- tests/unit/Utopia/Lists.php | 2 +- tests/unit/Utopia/Nested.php | 2 +- tests/unit/Utopia/Request/Filters/V15Test.php | 26 +- .../unit/Utopia/Response/Filters/V15Test.php | 54 +- tests/unit/Utopia/ResponseTest.php | 13 +- tests/unit/Utopia/Single.php | 4 +- 382 files changed, 10227 insertions(+), 10339 deletions(-) diff --git a/app/cli.php b/app/cli.php index d1dd885775..2614e00e11 100644 --- a/app/cli.php +++ b/app/cli.php @@ -1,27 +1,27 @@ $register); +CLI::setResource('register', fn () => $register); CLI::setResource('cache', function ($pools) { $list = Config::getParam('pools-cache', []); @@ -31,8 +31,7 @@ CLI::setResource('cache', function ($pools) { $adapters[] = $pools ->get($value) ->pop() - ->getResource() - ; + ->getResource(); } return new Cache(new Sharding($adapters)); @@ -64,7 +63,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { $collections = Config::getParam('collections', [])['console']; $last = \array_key_last($collections); - if (!($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */ + if (! ($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */ throw new Exception('Tables not ready yet.'); } @@ -76,8 +75,8 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { } } while ($attempts < $maxAttempts); - if (!$ready) { - throw new Exception("Console is not ready yet. Please try again later."); + if (! $ready) { + throw new Exception('Console is not ready yet. Please try again later.'); } return $dbForConsole; @@ -95,7 +94,8 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - $database->setNamespace('_' . $project->getInternalId()); + $database->setNamespace('_'.$project->getInternalId()); + return $database; } @@ -108,7 +108,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; - $database->setNamespace('_' . $project->getInternalId()); + $database->setNamespace('_'.$project->getInternalId()); return $database; }; @@ -116,7 +116,6 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $getProjectDB; }, ['pools', 'dbForConsole', 'cache']); - CLI::setResource('queueForFunctions', function (Group $pools) { return new Func($pools->get('queue')->pop()->getResource()); }, ['pools']); @@ -149,7 +148,7 @@ CLI::setResource('logError', function (Registry $register) { $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('Usage stats log pushed with status code: ' . $responseCode); + Console::info('Usage stats log pushed with status code: '.$responseCode); } Console::warning("Failed: {$error->getMessage()}"); diff --git a/app/config/authProviders.php b/app/config/authProviders.php index dedb4ec665..cf9ad052c3 100644 --- a/app/config/authProviders.php +++ b/app/config/authProviders.php @@ -69,7 +69,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'box' => [ 'name' => 'Box', @@ -79,7 +79,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'dailymotion' => [ 'name' => 'Dailymotion', @@ -89,7 +89,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'discord' => [ 'name' => 'Discord', @@ -229,7 +229,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'paypalSandbox' => [ 'name' => 'PayPal Sandbox', @@ -239,7 +239,7 @@ return [ // Ordered by ABC. 'sandbox' => true, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'podio' => [ 'name' => 'Podio', @@ -289,7 +289,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'tradeshift' => [ 'name' => 'Tradeshift', @@ -329,7 +329,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false + 'mock' => false, ], 'yahoo' => [ 'name' => 'Yahoo', diff --git a/app/config/avatars/browsers.php b/app/config/avatars/browsers.php index e7d31c7443..7d80937bd3 100644 --- a/app/config/avatars/browsers.php +++ b/app/config/avatars/browsers.php @@ -2,21 +2,20 @@ return [ // Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php - 'aa' => ['name' => 'Avant Browser', 'path' => __DIR__ . '/browsers/avant.png'], - 'an' => ['name' => 'Android WebView Beta', 'path' => __DIR__ . '/browsers/android-webview-beta.png'], - 'ch' => ['name' => 'Google Chrome', 'path' => __DIR__ . '/browsers/chrome.png'], - 'ci' => ['name' => 'Google Chrome (iOS)', 'path' => __DIR__ . '/browsers/chrome.png'], - 'cm' => ['name' => 'Google Chrome (Mobile)', 'path' => __DIR__ . '/browsers/chrome.png'], - 'cr' => ['name' => 'Chromium', 'path' => __DIR__ . '/browsers/chromium.png'], - 'ff' => ['name' => 'Mozilla Firefox', 'path' => __DIR__ . '/browsers/firefox.png'], - 'sf' => ['name' => 'Safari', 'path' => __DIR__ . '/browsers/safari.png'], - 'mf' => ['name' => 'Mobile Safari', 'path' => __DIR__ . '/browsers/safari.png'], - 'ps' => ['name' => 'Microsoft Edge', 'path' => __DIR__ . '/browsers/edge.png'], - 'oi' => ['name' => 'Microsoft Edge (iOS)', 'path' => __DIR__ . '/browsers/edge.png'], - 'om' => ['name' => 'Opera Mini', 'path' => __DIR__ . '/browsers/opera-mini.png'], - 'op' => ['name' => 'Opera', 'path' => __DIR__ . '/browsers/opera.png'], - 'on' => ['name' => 'Opera (Next)', 'path' => __DIR__ . '/browsers/opera.png'], - + 'aa' => ['name' => 'Avant Browser', 'path' => __DIR__.'/browsers/avant.png'], + 'an' => ['name' => 'Android WebView Beta', 'path' => __DIR__.'/browsers/android-webview-beta.png'], + 'ch' => ['name' => 'Google Chrome', 'path' => __DIR__.'/browsers/chrome.png'], + 'ci' => ['name' => 'Google Chrome (iOS)', 'path' => __DIR__.'/browsers/chrome.png'], + 'cm' => ['name' => 'Google Chrome (Mobile)', 'path' => __DIR__.'/browsers/chrome.png'], + 'cr' => ['name' => 'Chromium', 'path' => __DIR__.'/browsers/chromium.png'], + 'ff' => ['name' => 'Mozilla Firefox', 'path' => __DIR__.'/browsers/firefox.png'], + 'sf' => ['name' => 'Safari', 'path' => __DIR__.'/browsers/safari.png'], + 'mf' => ['name' => 'Mobile Safari', 'path' => __DIR__.'/browsers/safari.png'], + 'ps' => ['name' => 'Microsoft Edge', 'path' => __DIR__.'/browsers/edge.png'], + 'oi' => ['name' => 'Microsoft Edge (iOS)', 'path' => __DIR__.'/browsers/edge.png'], + 'om' => ['name' => 'Opera Mini', 'path' => __DIR__.'/browsers/opera-mini.png'], + 'op' => ['name' => 'Opera', 'path' => __DIR__.'/browsers/opera.png'], + 'on' => ['name' => 'Opera (Next)', 'path' => __DIR__.'/browsers/opera.png'], /* '36' => '360 Phone Browser', diff --git a/app/config/avatars/credit-cards.php b/app/config/avatars/credit-cards.php index aaef17ee3f..0655c6fcda 100644 --- a/app/config/avatars/credit-cards.php +++ b/app/config/avatars/credit-cards.php @@ -1,20 +1,20 @@ ['name' => 'American Express', 'path' => __DIR__ . '/credit-cards/amex.png'], - 'argencard' => ['name' => 'Argencard', 'path' => __DIR__ . '/credit-cards/argencard.png'], - 'cabal' => ['name' => 'Cabal', 'path' => __DIR__ . '/credit-cards/cabal.png'], - 'censosud' => ['name' => 'Consosud', 'path' => __DIR__ . '/credit-cards/consosud.png'], - 'diners' => ['name' => 'Diners Club', 'path' => __DIR__ . '/credit-cards/diners.png'], - 'discover' => ['name' => 'Discover', 'path' => __DIR__ . '/credit-cards/discover.png'], - 'elo' => ['name' => 'Elo', 'path' => __DIR__ . '/credit-cards/elo.png'], - 'hipercard' => ['name' => 'Hipercard', 'path' => __DIR__ . '/credit-cards/hipercard.png'], - 'jcb' => ['name' => 'JCB', 'path' => __DIR__ . '/credit-cards/jcb.png'], - 'mastercard' => ['name' => 'Mastercard', 'path' => __DIR__ . '/credit-cards/mastercard.png'], - 'naranja' => ['name' => 'Naranja', 'path' => __DIR__ . '/credit-cards/naranja.png'], - 'targeta-shopping' => ['name' => 'Tarjeta Shopping', 'path' => __DIR__ . '/credit-cards/tarjeta-shopping.png'], - 'union-china-pay' => ['name' => 'Union China Pay', 'path' => __DIR__ . '/credit-cards/union-china-pay.png'], - 'visa' => ['name' => 'Visa', 'path' => __DIR__ . '/credit-cards/visa.png'], - 'mir' => ['name' => 'MIR', 'path' => __DIR__ . '/credit-cards/mir.png'], - 'maestro' => ['name' => 'Maestro', 'path' => __DIR__ . '/credit-cards/maestro.png'] - ]; + 'amex' => ['name' => 'American Express', 'path' => __DIR__.'/credit-cards/amex.png'], + 'argencard' => ['name' => 'Argencard', 'path' => __DIR__.'/credit-cards/argencard.png'], + 'cabal' => ['name' => 'Cabal', 'path' => __DIR__.'/credit-cards/cabal.png'], + 'censosud' => ['name' => 'Consosud', 'path' => __DIR__.'/credit-cards/consosud.png'], + 'diners' => ['name' => 'Diners Club', 'path' => __DIR__.'/credit-cards/diners.png'], + 'discover' => ['name' => 'Discover', 'path' => __DIR__.'/credit-cards/discover.png'], + 'elo' => ['name' => 'Elo', 'path' => __DIR__.'/credit-cards/elo.png'], + 'hipercard' => ['name' => 'Hipercard', 'path' => __DIR__.'/credit-cards/hipercard.png'], + 'jcb' => ['name' => 'JCB', 'path' => __DIR__.'/credit-cards/jcb.png'], + 'mastercard' => ['name' => 'Mastercard', 'path' => __DIR__.'/credit-cards/mastercard.png'], + 'naranja' => ['name' => 'Naranja', 'path' => __DIR__.'/credit-cards/naranja.png'], + 'targeta-shopping' => ['name' => 'Tarjeta Shopping', 'path' => __DIR__.'/credit-cards/tarjeta-shopping.png'], + 'union-china-pay' => ['name' => 'Union China Pay', 'path' => __DIR__.'/credit-cards/union-china-pay.png'], + 'visa' => ['name' => 'Visa', 'path' => __DIR__.'/credit-cards/visa.png'], + 'mir' => ['name' => 'MIR', 'path' => __DIR__.'/credit-cards/mir.png'], + 'maestro' => ['name' => 'Maestro', 'path' => __DIR__.'/credit-cards/maestro.png'], +]; diff --git a/app/config/avatars/flags.php b/app/config/avatars/flags.php index 696656738e..144a8bfd31 100644 --- a/app/config/avatars/flags.php +++ b/app/config/avatars/flags.php @@ -1,198 +1,198 @@ ['name' => 'Afghanistan', 'path' => __DIR__ . '/flags/af.png'], - 'ao' => ['name' => 'Angola', 'path' => __DIR__ . '/flags/ao.png'], - 'al' => ['name' => 'Albania', 'path' => __DIR__ . '/flags/al.png'], - 'ad' => ['name' => 'Andorra', 'path' => __DIR__ . '/flags/ad.png'], - 'ae' => ['name' => 'United Arab Emirates', 'path' => __DIR__ . '/flags/ae.png'], - 'ar' => ['name' => 'Argentina', 'path' => __DIR__ . '/flags/ar.png'], - 'am' => ['name' => 'Armenia', 'path' => __DIR__ . '/flags/am.png'], - 'ag' => ['name' => 'Antigua and Barbuda', 'path' => __DIR__ . '/flags/ag.png'], - 'au' => ['name' => 'Australia', 'path' => __DIR__ . '/flags/au.png'], - 'at' => ['name' => 'Austria', 'path' => __DIR__ . '/flags/at.png'], - 'az' => ['name' => 'Azerbaijan', 'path' => __DIR__ . '/flags/az.png'], - 'bi' => ['name' => 'Burundi', 'path' => __DIR__ . '/flags/bi.png'], - 'be' => ['name' => 'Belgium', 'path' => __DIR__ . '/flags/be.png'], - 'bj' => ['name' => 'Benin', 'path' => __DIR__ . '/flags/bj.png'], - 'bf' => ['name' => 'Burkina Faso', 'path' => __DIR__ . '/flags/bf.png'], - 'bd' => ['name' => 'Bangladesh', 'path' => __DIR__ . '/flags/bd.png'], - 'bg' => ['name' => 'Bulgaria', 'path' => __DIR__ . '/flags/bg.png'], - 'bh' => ['name' => 'Bahrain', 'path' => __DIR__ . '/flags/bh.png'], - 'bs' => ['name' => 'Bahamas', 'path' => __DIR__ . '/flags/bs.png'], - 'ba' => ['name' => 'Bosnia and Herzegovina', 'path' => __DIR__ . '/flags/ba.png'], - 'by' => ['name' => 'Belarus', 'path' => __DIR__ . '/flags/by.png'], - 'bz' => ['name' => 'Belize', 'path' => __DIR__ . '/flags/bz.png'], - 'bo' => ['name' => 'Bolivia', 'path' => __DIR__ . '/flags/bo.png'], - 'br' => ['name' => 'Brazil', 'path' => __DIR__ . '/flags/br.png'], - 'bb' => ['name' => 'Barbados', 'path' => __DIR__ . '/flags/bb.png'], - 'bn' => ['name' => 'Brunei Darussalam', 'path' => __DIR__ . '/flags/bn.png'], - 'bt' => ['name' => 'Bhutan', 'path' => __DIR__ . '/flags/bt.png'], - 'bw' => ['name' => 'Botswana', 'path' => __DIR__ . '/flags/bw.png'], - 'cf' => ['name' => 'Central African Republic', 'path' => __DIR__ . '/flags/cf.png'], - 'ca' => ['name' => 'Canada', 'path' => __DIR__ . '/flags/ca.png'], - 'ch' => ['name' => 'Switzerland', 'path' => __DIR__ . '/flags/ch.png'], - 'cl' => ['name' => 'Chile', 'path' => __DIR__ . '/flags/cl.png'], - 'cn' => ['name' => 'China', 'path' => __DIR__ . '/flags/cn.png'], - 'ci' => ['name' => 'Côte d\'Ivoire', 'path' => __DIR__ . '/flags/ci.png'], - 'cm' => ['name' => 'Cameroon', 'path' => __DIR__ . '/flags/cm.png'], - 'cd' => ['name' => 'Democratic Republic of the Congo', 'path' => __DIR__ . '/flags/cd.png'], - 'cg' => ['name' => 'Republic of the Congo', 'path' => __DIR__ . '/flags/cg.png'], - 'co' => ['name' => 'Colombia', 'path' => __DIR__ . '/flags/co.png'], - 'km' => ['name' => 'Comoros', 'path' => __DIR__ . '/flags/km.png'], - 'cv' => ['name' => 'Cape Verde', 'path' => __DIR__ . '/flags/cv.png'], - 'cr' => ['name' => 'Costa Rica', 'path' => __DIR__ . '/flags/cr.png'], - 'cu' => ['name' => 'Cuba', 'path' => __DIR__ . '/flags/cu.png'], - 'cy' => ['name' => 'Cyprus', 'path' => __DIR__ . '/flags/cy.png'], - 'cz' => ['name' => 'Czech Republic', 'path' => __DIR__ . '/flags/cz.png'], - 'de' => ['name' => 'Germany', 'path' => __DIR__ . '/flags/de.png'], - 'dj' => ['name' => 'Djibouti', 'path' => __DIR__ . '/flags/dj.png'], - 'dm' => ['name' => 'Dominica', 'path' => __DIR__ . '/flags/dm.png'], - 'dk' => ['name' => 'Denmark', 'path' => __DIR__ . '/flags/dk.png'], - 'do' => ['name' => 'Dominican Republic', 'path' => __DIR__ . '/flags/do.png'], - 'dz' => ['name' => 'Algeria', 'path' => __DIR__ . '/flags/dz.png'], - 'ec' => ['name' => 'Ecuador', 'path' => __DIR__ . '/flags/ec.png'], - 'eg' => ['name' => 'Egypt', 'path' => __DIR__ . '/flags/eg.png'], - 'er' => ['name' => 'Eritrea', 'path' => __DIR__ . '/flags/er.png'], - 'es' => ['name' => 'Spain', 'path' => __DIR__ . '/flags/es.png'], - 'ee' => ['name' => 'Estonia', 'path' => __DIR__ . '/flags/ee.png'], - 'et' => ['name' => 'Ethiopia', 'path' => __DIR__ . '/flags/et.png'], - 'fi' => ['name' => 'Finland', 'path' => __DIR__ . '/flags/fi.png'], - 'fj' => ['name' => 'Fiji', 'path' => __DIR__ . '/flags/fj.png'], - 'fr' => ['name' => 'France', 'path' => __DIR__ . '/flags/fr.png'], - 'fm' => ['name' => 'Micronesia (Federated States of)', 'path' => __DIR__ . '/flags/fm.png'], - 'ga' => ['name' => 'Gabon', 'path' => __DIR__ . '/flags/ga.png'], - 'gb' => ['name' => 'United Kingdom', 'path' => __DIR__ . '/flags/gb.png'], - 'ge' => ['name' => 'Georgia', 'path' => __DIR__ . '/flags/ge.png'], - 'gh' => ['name' => 'Ghana', 'path' => __DIR__ . '/flags/gh.png'], - 'gn' => ['name' => 'Guinea', 'path' => __DIR__ . '/flags/gn.png'], - 'gm' => ['name' => 'Gambia', 'path' => __DIR__ . '/flags/gm.png'], - 'gw' => ['name' => 'Guinea-Bissau', 'path' => __DIR__ . '/flags/gw.png'], - 'gq' => ['name' => 'Equatorial Guinea', 'path' => __DIR__ . '/flags/gq.png'], - 'gr' => ['name' => 'Greece', 'path' => __DIR__ . '/flags/gr.png'], - 'gd' => ['name' => 'Grenada', 'path' => __DIR__ . '/flags/gd.png'], - 'gt' => ['name' => 'Guatemala', 'path' => __DIR__ . '/flags/gt.png'], - 'gy' => ['name' => 'Guyana', 'path' => __DIR__ . '/flags/gy.png'], - 'hn' => ['name' => 'Honduras', 'path' => __DIR__ . '/flags/hn.png'], - 'hr' => ['name' => 'Croatia', 'path' => __DIR__ . '/flags/hr.png'], - 'ht' => ['name' => 'Haiti', 'path' => __DIR__ . '/flags/ht.png'], - 'hu' => ['name' => 'Hungary', 'path' => __DIR__ . '/flags/hu.png'], - 'id' => ['name' => 'Indonesia', 'path' => __DIR__ . '/flags/id.png'], - 'in' => ['name' => 'India', 'path' => __DIR__ . '/flags/in.png'], - 'ie' => ['name' => 'Ireland', 'path' => __DIR__ . '/flags/ie.png'], - 'ir' => ['name' => 'Iran (Islamic Republic of)', 'path' => __DIR__ . '/flags/ir.png'], - 'iq' => ['name' => 'Iraq', 'path' => __DIR__ . '/flags/iq.png'], - 'is' => ['name' => 'Iceland', 'path' => __DIR__ . '/flags/is.png'], - 'il' => ['name' => 'Israel', 'path' => __DIR__ . '/flags/il.png'], - 'it' => ['name' => 'Italy', 'path' => __DIR__ . '/flags/it.png'], - 'jm' => ['name' => 'Jamaica', 'path' => __DIR__ . '/flags/jm.png'], - 'jo' => ['name' => 'Jordan', 'path' => __DIR__ . '/flags/jo.png'], - 'jp' => ['name' => 'Japan', 'path' => __DIR__ . '/flags/jp.png'], - 'kz' => ['name' => 'Kazakhstan', 'path' => __DIR__ . '/flags/kz.png'], - 'ke' => ['name' => 'Kenya', 'path' => __DIR__ . '/flags/ke.png'], - 'kg' => ['name' => 'Kyrgyzstan', 'path' => __DIR__ . '/flags/kg.png'], - 'kh' => ['name' => 'Cambodia', 'path' => __DIR__ . '/flags/kh.png'], - 'ki' => ['name' => 'Kiribati', 'path' => __DIR__ . '/flags/ki.png'], - 'kn' => ['name' => 'Saint Kitts and Nevis', 'path' => __DIR__ . '/flags/kn.png'], - 'kr' => ['name' => 'South Korea', 'path' => __DIR__ . '/flags/kr.png'], - 'kw' => ['name' => 'Kuwait', 'path' => __DIR__ . '/flags/kw.png'], - 'la' => ['name' => 'Lao People\'s Democratic Republic', 'path' => __DIR__ . '/flags/la.png'], - 'lb' => ['name' => 'Lebanon', 'path' => __DIR__ . '/flags/lb.png'], - 'lr' => ['name' => 'Liberia', 'path' => __DIR__ . '/flags/lr.png'], - 'ly' => ['name' => 'Libya', 'path' => __DIR__ . '/flags/ly.png'], - 'lc' => ['name' => 'Saint Lucia', 'path' => __DIR__ . '/flags/lc.png'], - 'li' => ['name' => 'Liechtenstein', 'path' => __DIR__ . '/flags/li.png'], - 'lk' => ['name' => 'Sri Lanka', 'path' => __DIR__ . '/flags/lk.png'], - 'ls' => ['name' => 'Lesotho', 'path' => __DIR__ . '/flags/ls.png'], - 'lt' => ['name' => 'Lithuania', 'path' => __DIR__ . '/flags/lt.png'], - 'lu' => ['name' => 'Luxembourg', 'path' => __DIR__ . '/flags/lu.png'], - 'lv' => ['name' => 'Latvia', 'path' => __DIR__ . '/flags/lv.png'], - 'ma' => ['name' => 'Morocco', 'path' => __DIR__ . '/flags/ma.png'], - 'mc' => ['name' => 'Monaco', 'path' => __DIR__ . '/flags/mc.png'], - 'md' => ['name' => 'Moldova', 'path' => __DIR__ . '/flags/md.png'], - 'mg' => ['name' => 'Madagascar', 'path' => __DIR__ . '/flags/mg.png'], - 'mv' => ['name' => 'Maldives', 'path' => __DIR__ . '/flags/mv.png'], - 'mx' => ['name' => 'Mexico', 'path' => __DIR__ . '/flags/mx.png'], - 'mh' => ['name' => 'Marshall Islands', 'path' => __DIR__ . '/flags/mh.png'], - 'mk' => ['name' => 'North Macedonia', 'path' => __DIR__ . '/flags/mk.png'], - 'ml' => ['name' => 'Mali', 'path' => __DIR__ . '/flags/ml.png'], - 'mt' => ['name' => 'Malta', 'path' => __DIR__ . '/flags/mt.png'], - 'mm' => ['name' => 'Myanmar', 'path' => __DIR__ . '/flags/mm.png'], - 'me' => ['name' => 'Montenegro', 'path' => __DIR__ . '/flags/me.png'], - 'mn' => ['name' => 'Mongolia', 'path' => __DIR__ . '/flags/mn.png'], - 'mz' => ['name' => 'Mozambique', 'path' => __DIR__ . '/flags/mz.png'], - 'mr' => ['name' => 'Mauritania', 'path' => __DIR__ . '/flags/mr.png'], - 'mu' => ['name' => 'Mauritius', 'path' => __DIR__ . '/flags/mu.png'], - 'mw' => ['name' => 'Malawi', 'path' => __DIR__ . '/flags/mw.png'], - 'my' => ['name' => 'Malaysia', 'path' => __DIR__ . '/flags/my.png'], - 'na' => ['name' => 'Namibia', 'path' => __DIR__ . '/flags/na.png'], - 'ne' => ['name' => 'Niger', 'path' => __DIR__ . '/flags/ne.png'], - 'ng' => ['name' => 'Nigeria', 'path' => __DIR__ . '/flags/ng.png'], - 'ni' => ['name' => 'Nicaragua', 'path' => __DIR__ . '/flags/ni.png'], - 'nl' => ['name' => 'Netherlands', 'path' => __DIR__ . '/flags/nl.png'], - 'no' => ['name' => 'Norway', 'path' => __DIR__ . '/flags/no.png'], - 'np' => ['name' => 'Nepal', 'path' => __DIR__ . '/flags/np.png'], - 'nr' => ['name' => 'Nauru', 'path' => __DIR__ . '/flags/nr.png'], - 'nz' => ['name' => 'New Zealand', 'path' => __DIR__ . '/flags/nz.png'], - 'om' => ['name' => 'Oman', 'path' => __DIR__ . '/flags/om.png'], - 'pk' => ['name' => 'Pakistan', 'path' => __DIR__ . '/flags/pk.png'], - 'pa' => ['name' => 'Panama', 'path' => __DIR__ . '/flags/pa.png'], - 'pe' => ['name' => 'Peru', 'path' => __DIR__ . '/flags/pe.png'], - 'ph' => ['name' => 'Philippines', 'path' => __DIR__ . '/flags/ph.png'], - 'pw' => ['name' => 'Palau', 'path' => __DIR__ . '/flags/pw.png'], - 'pg' => ['name' => 'Papua New Guinea', 'path' => __DIR__ . '/flags/pg.png'], - 'pl' => ['name' => 'Poland', 'path' => __DIR__ . '/flags/pl.png'], - 'kp' => ['name' => 'North Korea', 'path' => __DIR__ . '/flags/kp.png'], - 'pt' => ['name' => 'Portugal', 'path' => __DIR__ . '/flags/pt.png'], - 'py' => ['name' => 'Paraguay', 'path' => __DIR__ . '/flags/py.png'], - 'qa' => ['name' => 'Qatar', 'path' => __DIR__ . '/flags/qa.png'], - 'ro' => ['name' => 'Romania', 'path' => __DIR__ . '/flags/ro.png'], - 'ru' => ['name' => 'Russia', 'path' => __DIR__ . '/flags/ru.png'], - 'rw' => ['name' => 'Rwanda', 'path' => __DIR__ . '/flags/rw.png'], - 'sa' => ['name' => 'Saudi Arabia', 'path' => __DIR__ . '/flags/sa.png'], - 'sd' => ['name' => 'Sudan', 'path' => __DIR__ . '/flags/sd.png'], - 'sn' => ['name' => 'Senegal', 'path' => __DIR__ . '/flags/sn.png'], - 'sg' => ['name' => 'Singapore', 'path' => __DIR__ . '/flags/sg.png'], - 'sb' => ['name' => 'Solomon Islands', 'path' => __DIR__ . '/flags/sb.png'], - 'sl' => ['name' => 'Sierra Leone', 'path' => __DIR__ . '/flags/sl.png'], - 'sv' => ['name' => 'El Salvador', 'path' => __DIR__ . '/flags/sv.png'], - 'sm' => ['name' => 'San Marino', 'path' => __DIR__ . '/flags/sm.png'], - 'so' => ['name' => 'Somalia', 'path' => __DIR__ . '/flags/so.png'], - 'rs' => ['name' => 'Serbia', 'path' => __DIR__ . '/flags/rs.png'], - 'ss' => ['name' => 'South Sudan', 'path' => __DIR__ . '/flags/ss.png'], - 'st' => ['name' => 'Sao Tome and Principe', 'path' => __DIR__ . '/flags/st.png'], - 'sr' => ['name' => 'Suriname', 'path' => __DIR__ . '/flags/sr.png'], - 'sk' => ['name' => 'Slovakia', 'path' => __DIR__ . '/flags/sk.png'], - 'si' => ['name' => 'Slovenia', 'path' => __DIR__ . '/flags/si.png'], - 'se' => ['name' => 'Sweden', 'path' => __DIR__ . '/flags/se.png'], - 'sz' => ['name' => 'Eswatini', 'path' => __DIR__ . '/flags/sz.png'], - 'sc' => ['name' => 'Seychelles', 'path' => __DIR__ . '/flags/sc.png'], - 'sy' => ['name' => 'Syria', 'path' => __DIR__ . '/flags/sy.png'], - 'td' => ['name' => 'Chad', 'path' => __DIR__ . '/flags/td.png'], - 'tg' => ['name' => 'Togo', 'path' => __DIR__ . '/flags/tg.png'], - 'th' => ['name' => 'Thailand', 'path' => __DIR__ . '/flags/th.png'], - 'tj' => ['name' => 'Tajikistan', 'path' => __DIR__ . '/flags/tj.png'], - 'tm' => ['name' => 'Turkmenistan', 'path' => __DIR__ . '/flags/tm.png'], - 'tl' => ['name' => 'Timor-Leste', 'path' => __DIR__ . '/flags/tl.png'], - 'to' => ['name' => 'Tonga', 'path' => __DIR__ . '/flags/to.png'], - 'tt' => ['name' => 'Trinidad and Tobago', 'path' => __DIR__ . '/flags/tt.png'], - 'tn' => ['name' => 'Tunisia', 'path' => __DIR__ . '/flags/tn.png'], - 'tr' => ['name' => 'Turkey', 'path' => __DIR__ . '/flags/tr.png'], - 'tv' => ['name' => 'Tuvalu', 'path' => __DIR__ . '/flags/tv.png'], - 'tz' => ['name' => 'Tanzania', 'path' => __DIR__ . '/flags/tz.png'], - 'ug' => ['name' => 'Uganda', 'path' => __DIR__ . '/flags/ug.png'], - 'ua' => ['name' => 'Ukraine', 'path' => __DIR__ . '/flags/ua.png'], - 'uy' => ['name' => 'Uruguay', 'path' => __DIR__ . '/flags/uy.png'], - 'us' => ['name' => 'United States', 'path' => __DIR__ . '/flags/us.png'], - 'uz' => ['name' => 'Uzbekistan', 'path' => __DIR__ . '/flags/uz.png'], - 'va' => ['name' => 'Vatican City', 'path' => __DIR__ . '/flags/va.png'], - 'vc' => ['name' => 'Saint Vincent and the Grenadines', 'path' => __DIR__ . '/flags/vc.png'], - 've' => ['name' => 'Venezuela', 'path' => __DIR__ . '/flags/ve.png'], - 'vn' => ['name' => 'Vietnam', 'path' => __DIR__ . '/flags/vn.png'], - 'vu' => ['name' => 'Vanuatu', 'path' => __DIR__ . '/flags/vu.png'], - 'ws' => ['name' => 'Samoa', 'path' => __DIR__ . '/flags/ws.png'], - 'ye' => ['name' => 'Yemen', 'path' => __DIR__ . '/flags/ye.png'], - 'za' => ['name' => 'South Africa', 'path' => __DIR__ . '/flags/za.png'], - 'zm' => ['name' => 'Zambia', 'path' => __DIR__ . '/flags/zm.png'], - 'zw' => ['name' => 'Zimbabwe', 'path' => __DIR__ . '/flags/zw.png'], + 'af' => ['name' => 'Afghanistan', 'path' => __DIR__.'/flags/af.png'], + 'ao' => ['name' => 'Angola', 'path' => __DIR__.'/flags/ao.png'], + 'al' => ['name' => 'Albania', 'path' => __DIR__.'/flags/al.png'], + 'ad' => ['name' => 'Andorra', 'path' => __DIR__.'/flags/ad.png'], + 'ae' => ['name' => 'United Arab Emirates', 'path' => __DIR__.'/flags/ae.png'], + 'ar' => ['name' => 'Argentina', 'path' => __DIR__.'/flags/ar.png'], + 'am' => ['name' => 'Armenia', 'path' => __DIR__.'/flags/am.png'], + 'ag' => ['name' => 'Antigua and Barbuda', 'path' => __DIR__.'/flags/ag.png'], + 'au' => ['name' => 'Australia', 'path' => __DIR__.'/flags/au.png'], + 'at' => ['name' => 'Austria', 'path' => __DIR__.'/flags/at.png'], + 'az' => ['name' => 'Azerbaijan', 'path' => __DIR__.'/flags/az.png'], + 'bi' => ['name' => 'Burundi', 'path' => __DIR__.'/flags/bi.png'], + 'be' => ['name' => 'Belgium', 'path' => __DIR__.'/flags/be.png'], + 'bj' => ['name' => 'Benin', 'path' => __DIR__.'/flags/bj.png'], + 'bf' => ['name' => 'Burkina Faso', 'path' => __DIR__.'/flags/bf.png'], + 'bd' => ['name' => 'Bangladesh', 'path' => __DIR__.'/flags/bd.png'], + 'bg' => ['name' => 'Bulgaria', 'path' => __DIR__.'/flags/bg.png'], + 'bh' => ['name' => 'Bahrain', 'path' => __DIR__.'/flags/bh.png'], + 'bs' => ['name' => 'Bahamas', 'path' => __DIR__.'/flags/bs.png'], + 'ba' => ['name' => 'Bosnia and Herzegovina', 'path' => __DIR__.'/flags/ba.png'], + 'by' => ['name' => 'Belarus', 'path' => __DIR__.'/flags/by.png'], + 'bz' => ['name' => 'Belize', 'path' => __DIR__.'/flags/bz.png'], + 'bo' => ['name' => 'Bolivia', 'path' => __DIR__.'/flags/bo.png'], + 'br' => ['name' => 'Brazil', 'path' => __DIR__.'/flags/br.png'], + 'bb' => ['name' => 'Barbados', 'path' => __DIR__.'/flags/bb.png'], + 'bn' => ['name' => 'Brunei Darussalam', 'path' => __DIR__.'/flags/bn.png'], + 'bt' => ['name' => 'Bhutan', 'path' => __DIR__.'/flags/bt.png'], + 'bw' => ['name' => 'Botswana', 'path' => __DIR__.'/flags/bw.png'], + 'cf' => ['name' => 'Central African Republic', 'path' => __DIR__.'/flags/cf.png'], + 'ca' => ['name' => 'Canada', 'path' => __DIR__.'/flags/ca.png'], + 'ch' => ['name' => 'Switzerland', 'path' => __DIR__.'/flags/ch.png'], + 'cl' => ['name' => 'Chile', 'path' => __DIR__.'/flags/cl.png'], + 'cn' => ['name' => 'China', 'path' => __DIR__.'/flags/cn.png'], + 'ci' => ['name' => 'Côte d\'Ivoire', 'path' => __DIR__.'/flags/ci.png'], + 'cm' => ['name' => 'Cameroon', 'path' => __DIR__.'/flags/cm.png'], + 'cd' => ['name' => 'Democratic Republic of the Congo', 'path' => __DIR__.'/flags/cd.png'], + 'cg' => ['name' => 'Republic of the Congo', 'path' => __DIR__.'/flags/cg.png'], + 'co' => ['name' => 'Colombia', 'path' => __DIR__.'/flags/co.png'], + 'km' => ['name' => 'Comoros', 'path' => __DIR__.'/flags/km.png'], + 'cv' => ['name' => 'Cape Verde', 'path' => __DIR__.'/flags/cv.png'], + 'cr' => ['name' => 'Costa Rica', 'path' => __DIR__.'/flags/cr.png'], + 'cu' => ['name' => 'Cuba', 'path' => __DIR__.'/flags/cu.png'], + 'cy' => ['name' => 'Cyprus', 'path' => __DIR__.'/flags/cy.png'], + 'cz' => ['name' => 'Czech Republic', 'path' => __DIR__.'/flags/cz.png'], + 'de' => ['name' => 'Germany', 'path' => __DIR__.'/flags/de.png'], + 'dj' => ['name' => 'Djibouti', 'path' => __DIR__.'/flags/dj.png'], + 'dm' => ['name' => 'Dominica', 'path' => __DIR__.'/flags/dm.png'], + 'dk' => ['name' => 'Denmark', 'path' => __DIR__.'/flags/dk.png'], + 'do' => ['name' => 'Dominican Republic', 'path' => __DIR__.'/flags/do.png'], + 'dz' => ['name' => 'Algeria', 'path' => __DIR__.'/flags/dz.png'], + 'ec' => ['name' => 'Ecuador', 'path' => __DIR__.'/flags/ec.png'], + 'eg' => ['name' => 'Egypt', 'path' => __DIR__.'/flags/eg.png'], + 'er' => ['name' => 'Eritrea', 'path' => __DIR__.'/flags/er.png'], + 'es' => ['name' => 'Spain', 'path' => __DIR__.'/flags/es.png'], + 'ee' => ['name' => 'Estonia', 'path' => __DIR__.'/flags/ee.png'], + 'et' => ['name' => 'Ethiopia', 'path' => __DIR__.'/flags/et.png'], + 'fi' => ['name' => 'Finland', 'path' => __DIR__.'/flags/fi.png'], + 'fj' => ['name' => 'Fiji', 'path' => __DIR__.'/flags/fj.png'], + 'fr' => ['name' => 'France', 'path' => __DIR__.'/flags/fr.png'], + 'fm' => ['name' => 'Micronesia (Federated States of)', 'path' => __DIR__.'/flags/fm.png'], + 'ga' => ['name' => 'Gabon', 'path' => __DIR__.'/flags/ga.png'], + 'gb' => ['name' => 'United Kingdom', 'path' => __DIR__.'/flags/gb.png'], + 'ge' => ['name' => 'Georgia', 'path' => __DIR__.'/flags/ge.png'], + 'gh' => ['name' => 'Ghana', 'path' => __DIR__.'/flags/gh.png'], + 'gn' => ['name' => 'Guinea', 'path' => __DIR__.'/flags/gn.png'], + 'gm' => ['name' => 'Gambia', 'path' => __DIR__.'/flags/gm.png'], + 'gw' => ['name' => 'Guinea-Bissau', 'path' => __DIR__.'/flags/gw.png'], + 'gq' => ['name' => 'Equatorial Guinea', 'path' => __DIR__.'/flags/gq.png'], + 'gr' => ['name' => 'Greece', 'path' => __DIR__.'/flags/gr.png'], + 'gd' => ['name' => 'Grenada', 'path' => __DIR__.'/flags/gd.png'], + 'gt' => ['name' => 'Guatemala', 'path' => __DIR__.'/flags/gt.png'], + 'gy' => ['name' => 'Guyana', 'path' => __DIR__.'/flags/gy.png'], + 'hn' => ['name' => 'Honduras', 'path' => __DIR__.'/flags/hn.png'], + 'hr' => ['name' => 'Croatia', 'path' => __DIR__.'/flags/hr.png'], + 'ht' => ['name' => 'Haiti', 'path' => __DIR__.'/flags/ht.png'], + 'hu' => ['name' => 'Hungary', 'path' => __DIR__.'/flags/hu.png'], + 'id' => ['name' => 'Indonesia', 'path' => __DIR__.'/flags/id.png'], + 'in' => ['name' => 'India', 'path' => __DIR__.'/flags/in.png'], + 'ie' => ['name' => 'Ireland', 'path' => __DIR__.'/flags/ie.png'], + 'ir' => ['name' => 'Iran (Islamic Republic of)', 'path' => __DIR__.'/flags/ir.png'], + 'iq' => ['name' => 'Iraq', 'path' => __DIR__.'/flags/iq.png'], + 'is' => ['name' => 'Iceland', 'path' => __DIR__.'/flags/is.png'], + 'il' => ['name' => 'Israel', 'path' => __DIR__.'/flags/il.png'], + 'it' => ['name' => 'Italy', 'path' => __DIR__.'/flags/it.png'], + 'jm' => ['name' => 'Jamaica', 'path' => __DIR__.'/flags/jm.png'], + 'jo' => ['name' => 'Jordan', 'path' => __DIR__.'/flags/jo.png'], + 'jp' => ['name' => 'Japan', 'path' => __DIR__.'/flags/jp.png'], + 'kz' => ['name' => 'Kazakhstan', 'path' => __DIR__.'/flags/kz.png'], + 'ke' => ['name' => 'Kenya', 'path' => __DIR__.'/flags/ke.png'], + 'kg' => ['name' => 'Kyrgyzstan', 'path' => __DIR__.'/flags/kg.png'], + 'kh' => ['name' => 'Cambodia', 'path' => __DIR__.'/flags/kh.png'], + 'ki' => ['name' => 'Kiribati', 'path' => __DIR__.'/flags/ki.png'], + 'kn' => ['name' => 'Saint Kitts and Nevis', 'path' => __DIR__.'/flags/kn.png'], + 'kr' => ['name' => 'South Korea', 'path' => __DIR__.'/flags/kr.png'], + 'kw' => ['name' => 'Kuwait', 'path' => __DIR__.'/flags/kw.png'], + 'la' => ['name' => 'Lao People\'s Democratic Republic', 'path' => __DIR__.'/flags/la.png'], + 'lb' => ['name' => 'Lebanon', 'path' => __DIR__.'/flags/lb.png'], + 'lr' => ['name' => 'Liberia', 'path' => __DIR__.'/flags/lr.png'], + 'ly' => ['name' => 'Libya', 'path' => __DIR__.'/flags/ly.png'], + 'lc' => ['name' => 'Saint Lucia', 'path' => __DIR__.'/flags/lc.png'], + 'li' => ['name' => 'Liechtenstein', 'path' => __DIR__.'/flags/li.png'], + 'lk' => ['name' => 'Sri Lanka', 'path' => __DIR__.'/flags/lk.png'], + 'ls' => ['name' => 'Lesotho', 'path' => __DIR__.'/flags/ls.png'], + 'lt' => ['name' => 'Lithuania', 'path' => __DIR__.'/flags/lt.png'], + 'lu' => ['name' => 'Luxembourg', 'path' => __DIR__.'/flags/lu.png'], + 'lv' => ['name' => 'Latvia', 'path' => __DIR__.'/flags/lv.png'], + 'ma' => ['name' => 'Morocco', 'path' => __DIR__.'/flags/ma.png'], + 'mc' => ['name' => 'Monaco', 'path' => __DIR__.'/flags/mc.png'], + 'md' => ['name' => 'Moldova', 'path' => __DIR__.'/flags/md.png'], + 'mg' => ['name' => 'Madagascar', 'path' => __DIR__.'/flags/mg.png'], + 'mv' => ['name' => 'Maldives', 'path' => __DIR__.'/flags/mv.png'], + 'mx' => ['name' => 'Mexico', 'path' => __DIR__.'/flags/mx.png'], + 'mh' => ['name' => 'Marshall Islands', 'path' => __DIR__.'/flags/mh.png'], + 'mk' => ['name' => 'North Macedonia', 'path' => __DIR__.'/flags/mk.png'], + 'ml' => ['name' => 'Mali', 'path' => __DIR__.'/flags/ml.png'], + 'mt' => ['name' => 'Malta', 'path' => __DIR__.'/flags/mt.png'], + 'mm' => ['name' => 'Myanmar', 'path' => __DIR__.'/flags/mm.png'], + 'me' => ['name' => 'Montenegro', 'path' => __DIR__.'/flags/me.png'], + 'mn' => ['name' => 'Mongolia', 'path' => __DIR__.'/flags/mn.png'], + 'mz' => ['name' => 'Mozambique', 'path' => __DIR__.'/flags/mz.png'], + 'mr' => ['name' => 'Mauritania', 'path' => __DIR__.'/flags/mr.png'], + 'mu' => ['name' => 'Mauritius', 'path' => __DIR__.'/flags/mu.png'], + 'mw' => ['name' => 'Malawi', 'path' => __DIR__.'/flags/mw.png'], + 'my' => ['name' => 'Malaysia', 'path' => __DIR__.'/flags/my.png'], + 'na' => ['name' => 'Namibia', 'path' => __DIR__.'/flags/na.png'], + 'ne' => ['name' => 'Niger', 'path' => __DIR__.'/flags/ne.png'], + 'ng' => ['name' => 'Nigeria', 'path' => __DIR__.'/flags/ng.png'], + 'ni' => ['name' => 'Nicaragua', 'path' => __DIR__.'/flags/ni.png'], + 'nl' => ['name' => 'Netherlands', 'path' => __DIR__.'/flags/nl.png'], + 'no' => ['name' => 'Norway', 'path' => __DIR__.'/flags/no.png'], + 'np' => ['name' => 'Nepal', 'path' => __DIR__.'/flags/np.png'], + 'nr' => ['name' => 'Nauru', 'path' => __DIR__.'/flags/nr.png'], + 'nz' => ['name' => 'New Zealand', 'path' => __DIR__.'/flags/nz.png'], + 'om' => ['name' => 'Oman', 'path' => __DIR__.'/flags/om.png'], + 'pk' => ['name' => 'Pakistan', 'path' => __DIR__.'/flags/pk.png'], + 'pa' => ['name' => 'Panama', 'path' => __DIR__.'/flags/pa.png'], + 'pe' => ['name' => 'Peru', 'path' => __DIR__.'/flags/pe.png'], + 'ph' => ['name' => 'Philippines', 'path' => __DIR__.'/flags/ph.png'], + 'pw' => ['name' => 'Palau', 'path' => __DIR__.'/flags/pw.png'], + 'pg' => ['name' => 'Papua New Guinea', 'path' => __DIR__.'/flags/pg.png'], + 'pl' => ['name' => 'Poland', 'path' => __DIR__.'/flags/pl.png'], + 'kp' => ['name' => 'North Korea', 'path' => __DIR__.'/flags/kp.png'], + 'pt' => ['name' => 'Portugal', 'path' => __DIR__.'/flags/pt.png'], + 'py' => ['name' => 'Paraguay', 'path' => __DIR__.'/flags/py.png'], + 'qa' => ['name' => 'Qatar', 'path' => __DIR__.'/flags/qa.png'], + 'ro' => ['name' => 'Romania', 'path' => __DIR__.'/flags/ro.png'], + 'ru' => ['name' => 'Russia', 'path' => __DIR__.'/flags/ru.png'], + 'rw' => ['name' => 'Rwanda', 'path' => __DIR__.'/flags/rw.png'], + 'sa' => ['name' => 'Saudi Arabia', 'path' => __DIR__.'/flags/sa.png'], + 'sd' => ['name' => 'Sudan', 'path' => __DIR__.'/flags/sd.png'], + 'sn' => ['name' => 'Senegal', 'path' => __DIR__.'/flags/sn.png'], + 'sg' => ['name' => 'Singapore', 'path' => __DIR__.'/flags/sg.png'], + 'sb' => ['name' => 'Solomon Islands', 'path' => __DIR__.'/flags/sb.png'], + 'sl' => ['name' => 'Sierra Leone', 'path' => __DIR__.'/flags/sl.png'], + 'sv' => ['name' => 'El Salvador', 'path' => __DIR__.'/flags/sv.png'], + 'sm' => ['name' => 'San Marino', 'path' => __DIR__.'/flags/sm.png'], + 'so' => ['name' => 'Somalia', 'path' => __DIR__.'/flags/so.png'], + 'rs' => ['name' => 'Serbia', 'path' => __DIR__.'/flags/rs.png'], + 'ss' => ['name' => 'South Sudan', 'path' => __DIR__.'/flags/ss.png'], + 'st' => ['name' => 'Sao Tome and Principe', 'path' => __DIR__.'/flags/st.png'], + 'sr' => ['name' => 'Suriname', 'path' => __DIR__.'/flags/sr.png'], + 'sk' => ['name' => 'Slovakia', 'path' => __DIR__.'/flags/sk.png'], + 'si' => ['name' => 'Slovenia', 'path' => __DIR__.'/flags/si.png'], + 'se' => ['name' => 'Sweden', 'path' => __DIR__.'/flags/se.png'], + 'sz' => ['name' => 'Eswatini', 'path' => __DIR__.'/flags/sz.png'], + 'sc' => ['name' => 'Seychelles', 'path' => __DIR__.'/flags/sc.png'], + 'sy' => ['name' => 'Syria', 'path' => __DIR__.'/flags/sy.png'], + 'td' => ['name' => 'Chad', 'path' => __DIR__.'/flags/td.png'], + 'tg' => ['name' => 'Togo', 'path' => __DIR__.'/flags/tg.png'], + 'th' => ['name' => 'Thailand', 'path' => __DIR__.'/flags/th.png'], + 'tj' => ['name' => 'Tajikistan', 'path' => __DIR__.'/flags/tj.png'], + 'tm' => ['name' => 'Turkmenistan', 'path' => __DIR__.'/flags/tm.png'], + 'tl' => ['name' => 'Timor-Leste', 'path' => __DIR__.'/flags/tl.png'], + 'to' => ['name' => 'Tonga', 'path' => __DIR__.'/flags/to.png'], + 'tt' => ['name' => 'Trinidad and Tobago', 'path' => __DIR__.'/flags/tt.png'], + 'tn' => ['name' => 'Tunisia', 'path' => __DIR__.'/flags/tn.png'], + 'tr' => ['name' => 'Turkey', 'path' => __DIR__.'/flags/tr.png'], + 'tv' => ['name' => 'Tuvalu', 'path' => __DIR__.'/flags/tv.png'], + 'tz' => ['name' => 'Tanzania', 'path' => __DIR__.'/flags/tz.png'], + 'ug' => ['name' => 'Uganda', 'path' => __DIR__.'/flags/ug.png'], + 'ua' => ['name' => 'Ukraine', 'path' => __DIR__.'/flags/ua.png'], + 'uy' => ['name' => 'Uruguay', 'path' => __DIR__.'/flags/uy.png'], + 'us' => ['name' => 'United States', 'path' => __DIR__.'/flags/us.png'], + 'uz' => ['name' => 'Uzbekistan', 'path' => __DIR__.'/flags/uz.png'], + 'va' => ['name' => 'Vatican City', 'path' => __DIR__.'/flags/va.png'], + 'vc' => ['name' => 'Saint Vincent and the Grenadines', 'path' => __DIR__.'/flags/vc.png'], + 've' => ['name' => 'Venezuela', 'path' => __DIR__.'/flags/ve.png'], + 'vn' => ['name' => 'Vietnam', 'path' => __DIR__.'/flags/vn.png'], + 'vu' => ['name' => 'Vanuatu', 'path' => __DIR__.'/flags/vu.png'], + 'ws' => ['name' => 'Samoa', 'path' => __DIR__.'/flags/ws.png'], + 'ye' => ['name' => 'Yemen', 'path' => __DIR__.'/flags/ye.png'], + 'za' => ['name' => 'South Africa', 'path' => __DIR__.'/flags/za.png'], + 'zm' => ['name' => 'Zambia', 'path' => __DIR__.'/flags/zm.png'], + 'zw' => ['name' => 'Zimbabwe', 'path' => __DIR__.'/flags/zw.png'], ]; diff --git a/app/config/avatars/os.php b/app/config/avatars/os.php index f500eed759..ba5ee0e1fc 100644 --- a/app/config/avatars/os.php +++ b/app/config/avatars/os.php @@ -2,9 +2,9 @@ return [ // Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php - 'AND' => __DIR__ . '/os/android.png', - 'ATV' => __DIR__ . '/os/apple-tv.png', - 'COS' => __DIR__ . '/os/chrome-os.png', + 'AND' => __DIR__.'/os/android.png', + 'ATV' => __DIR__.'/os/apple-tv.png', + 'COS' => __DIR__.'/os/chrome-os.png', /* 'AIX' => 'AIX', diff --git a/app/config/collections.php b/app/config/collections.php index c9005f8217..af68b4174e 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -16,7 +16,6 @@ $auth = Config::getParam('auth', []); * attributes => list of attributes * indexes => list of indexes */ - $commonCollections = [ 'users' => [ '$collection' => ID::custom(Database::METADATA), @@ -253,7 +252,7 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => ['datetime'], - ] + ], ], 'indexes' => [ [ @@ -410,7 +409,7 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => [], - ] + ], ], 'indexes' => [ [ @@ -1278,7 +1277,7 @@ $commonCollections = [ 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], - ] + ], ], 'stats' => [ @@ -1454,7 +1453,7 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => ['json', 'encrypt'], - ] + ], ], 'indexes' => [ [ @@ -1470,7 +1469,7 @@ $commonCollections = [ 'attributes' => ['name'], 'lengths' => [128], 'orders' => [Database::ORDER_ASC], - ] + ], ], ], @@ -1811,7 +1810,7 @@ $commonCollections = [ 'attributes' => ['topicInternalId'], 'lengths' => [], 'orders' => [], - ] + ], ], ], @@ -1924,7 +1923,7 @@ $commonCollections = [ 'orders' => [], ], ], - ] + ], ]; $projectCollections = array_merge([ @@ -2667,7 +2666,7 @@ $projectCollections = array_merge([ 'default' => false, 'array' => false, 'filters' => [], - ] + ], ], 'indexes' => [ [ @@ -2858,7 +2857,7 @@ $projectCollections = array_merge([ 'default' => '', 'array' => false, 'filters' => [], - ] + ], ], 'indexes' => [ [ @@ -2867,7 +2866,7 @@ $projectCollections = array_merge([ 'attributes' => ['deploymentId'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], - ] + ], ], ], @@ -3102,7 +3101,7 @@ $projectCollections = array_merge([ 'required' => true, 'default' => null, 'array' => false, - 'filters' => [ 'encrypt' ] + 'filters' => ['encrypt'], ], [ '$id' => ID::custom('search'), @@ -3186,7 +3185,7 @@ $projectCollections = array_merge([ 'array' => false, 'filters' => [], ], - ], + ], 'indexes' => [ [ '$id' => '_key_accessedAt', @@ -3308,7 +3307,7 @@ $projectCollections = array_merge([ 'default' => null, 'array' => false, 'filters' => [], - ] + ], ], 'indexes' => [ [ @@ -3338,7 +3337,7 @@ $projectCollections = array_merge([ 'attributes' => ['search'], 'lengths' => [], 'orders' => [], - ] + ], ], ], ], $commonCollections); @@ -3748,7 +3747,7 @@ $consoleCollections = array_merge([ [ '$id' => ID::custom('_key_region_resourceType_resourceUpdatedAt'), 'type' => Database::INDEX_KEY, - 'attributes' => ['region', 'resourceType','resourceUpdatedAt'], + 'attributes' => ['region', 'resourceType', 'resourceUpdatedAt'], 'lengths' => [], 'orders' => [], ], @@ -3843,7 +3842,7 @@ $consoleCollections = array_merge([ 'default' => null, 'array' => false, 'filters' => [], - ] + ], ], 'indexes' => [ [ @@ -4185,7 +4184,7 @@ $consoleCollections = array_merge([ 'attributes' => ['projectInternalId'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], - ] + ], ], ], @@ -4312,7 +4311,7 @@ $consoleCollections = array_merge([ 'default' => null, 'array' => false, 'filters' => [], //TODO: use json filter - ] + ], ], 'indexes' => [ [ @@ -4322,7 +4321,7 @@ $consoleCollections = array_merge([ 'lengths' => [], 'orders' => [Database::ORDER_DESC], ], - ] + ], ], ], $commonCollections); @@ -4588,7 +4587,7 @@ $bucketCollections = [ 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], - ] + ], ], ]; @@ -4711,15 +4710,14 @@ $dbCollections = [ 'orders' => [Database::ORDER_ASC], ], ], - ] + ], ]; - $collections = [ 'projects' => $projectCollections, - 'console' => $consoleCollections, + 'console' => $consoleCollections, 'buckets' => $bucketCollections, - 'databases' => $dbCollections + 'databases' => $dbCollections, ]; return $collections; diff --git a/app/config/errors.php b/app/config/errors.php index 5942c6027c..8b11410996 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -299,7 +299,7 @@ return [ Exception::AVATAR_SET_NOT_FOUND => [ 'name' => Exception::AVATAR_SET_NOT_FOUND, 'description' => 'The requested avatar set could not be found.', - 'code' => 404 + 'code' => 404, ], Exception::AVATAR_NOT_FOUND => [ 'name' => Exception::AVATAR_NOT_FOUND, @@ -426,13 +426,13 @@ return [ Exception::DATABASE_NOT_FOUND => [ 'name' => Exception::DATABASE_NOT_FOUND, 'description' => 'Database not found', - 'code' => 404 + 'code' => 404, ], Exception::DATABASE_ALREADY_EXISTS => [ 'name' => Exception::DATABASE_ALREADY_EXISTS, 'description' => 'Database already exists', - 'code' => 409 + 'code' => 409, ], /** Collections */ @@ -702,5 +702,5 @@ return [ 'name' => Exception::PROVIDER_INCORRECT_TYPE, 'description' => 'Provider with the request ID is of incorrect type: ', 'code' => 400, - ] + ], ]; diff --git a/app/config/events.php b/app/config/events.php index 45bb45fbf8..4ecc651240 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -19,7 +19,7 @@ return [ '$description' => 'This event triggers when a session for a user is created.', ], 'delete' => [ - '$description' => 'This event triggers when a session for a user is deleted.' + '$description' => 'This event triggers when a session for a user is deleted.', ], ], 'recovery' => [ @@ -30,7 +30,7 @@ return [ '$description' => 'This event triggers when a recovery token for a user is created.', ], 'update' => [ - '$description' => 'This event triggers when a recovery token for a user is validated.' + '$description' => 'This event triggers when a recovery token for a user is validated.', ], ], 'verification' => [ @@ -41,7 +41,7 @@ return [ '$description' => 'This event triggers when a verification token for a user is created.', ], 'update' => [ - '$description' => 'This event triggers when a verification token for a user is validated.' + '$description' => 'This event triggers when a verification token for a user is validated.', ], ], 'targets' => [ @@ -59,7 +59,7 @@ return [ ], ], 'create' => [ - '$description' => 'This event triggers when a user is created.' + '$description' => 'This event triggers when a user is created.', ], 'delete' => [ '$description' => 'This event triggers when a user is deleted.', @@ -81,7 +81,7 @@ return [ 'prefs' => [ '$description' => 'This event triggers when a user\'s preferences is updated.', ], - ] + ], ], 'databases' => [ '$model' => Response::MODEL_DATABASE, @@ -99,10 +99,10 @@ return [ '$description' => 'This event triggers when a document is created.', ], 'delete' => [ - '$description' => 'This event triggers when a document is deleted.' + '$description' => 'This event triggers when a document is deleted.', ], 'update' => [ - '$description' => 'This event triggers when a document is updated.' + '$description' => 'This event triggers when a document is updated.', ], ], 'indexes' => [ @@ -113,8 +113,8 @@ return [ '$description' => 'This event triggers when an index is created.', ], 'delete' => [ - '$description' => 'This event triggers when an index is deleted.' - ] + '$description' => 'This event triggers when an index is deleted.', + ], ], 'attributes' => [ '$model' => Response::MODEL_ATTRIBUTE, @@ -124,28 +124,28 @@ return [ '$description' => 'This event triggers when an attribute is created.', ], 'delete' => [ - '$description' => 'This event triggers when an attribute is deleted.' - ] + '$description' => 'This event triggers when an attribute is deleted.', + ], ], 'create' => [ - '$description' => 'This event triggers when a collection is created.' + '$description' => 'This event triggers when a collection is created.', ], 'delete' => [ '$description' => 'This event triggers when a collection is deleted.', ], 'update' => [ '$description' => 'This event triggers when a collection is updated.', - ] + ], ], 'create' => [ - '$description' => 'This event triggers when a database is created.' + '$description' => 'This event triggers when a database is created.', ], 'delete' => [ '$description' => 'This event triggers when a database is deleted.', ], 'update' => [ '$description' => 'This event triggers when a database is updated.', - ] + ], ], 'buckets' => [ '$model' => Response::MODEL_BUCKET, @@ -159,21 +159,21 @@ return [ '$description' => 'This event triggers when a file is created.', ], 'delete' => [ - '$description' => 'This event triggers when a file is deleted.' + '$description' => 'This event triggers when a file is deleted.', ], 'update' => [ - '$description' => 'This event triggers when a file is updated.' + '$description' => 'This event triggers when a file is updated.', ], ], 'create' => [ - '$description' => 'This event triggers when a bucket is created.' + '$description' => 'This event triggers when a bucket is created.', ], 'delete' => [ '$description' => 'This event triggers when a bucket is deleted.', ], 'update' => [ '$description' => 'This event triggers when a bucket is updated.', - ] + ], ], 'teams' => [ '$model' => Response::MODEL_TEAM, @@ -187,17 +187,17 @@ return [ '$description' => 'This event triggers when a membership is created.', ], 'delete' => [ - '$description' => 'This event triggers when a membership is deleted.' + '$description' => 'This event triggers when a membership is deleted.', ], 'update' => [ '$description' => 'This event triggers when a membership is updated.', 'status' => [ - '$description' => 'This event triggers when a team memberships status is updated.' - ] + '$description' => 'This event triggers when a team memberships status is updated.', + ], ], ], 'create' => [ - '$description' => 'This event triggers when a team is created.' + '$description' => 'This event triggers when a team is created.', ], 'delete' => [ '$description' => 'This event triggers when a team is deleted.', @@ -207,7 +207,7 @@ return [ 'prefs' => [ '$description' => 'This event triggers when a team\'s preferences are updated.', ], - ] + ], ], 'functions' => [ '$model' => Response::MODEL_FUNCTION, @@ -221,10 +221,10 @@ return [ '$description' => 'This event triggers when a deployment is created.', ], 'delete' => [ - '$description' => 'This event triggers when a deployment is deleted.' + '$description' => 'This event triggers when a deployment is deleted.', ], 'update' => [ - '$description' => 'This event triggers when a deployment is updated.' + '$description' => 'This event triggers when a deployment is updated.', ], ], 'executions' => [ @@ -235,21 +235,21 @@ return [ '$description' => 'This event triggers when an execution is created.', ], 'delete' => [ - '$description' => 'This event triggers when an execution is deleted.' + '$description' => 'This event triggers when an execution is deleted.', ], 'update' => [ - '$description' => 'This event triggers when an execution is updated.' + '$description' => 'This event triggers when an execution is updated.', ], ], 'create' => [ - '$description' => 'This event triggers when a function is created.' + '$description' => 'This event triggers when a function is created.', ], 'delete' => [ '$description' => 'This event triggers when a function is deleted.', ], 'update' => [ '$description' => 'This event triggers when a function is updated.', - ] + ], ], 'messages' => [ '$model' => Response::MODEL_MESSAGE, @@ -269,7 +269,7 @@ return [ '$description' => 'This event triggers when a provider is updated.', ], 'delete' => [ - '$description' => 'This event triggers when a provider is deleted.' + '$description' => 'This event triggers when a provider is deleted.', ], ], 'topics' => [ @@ -280,7 +280,7 @@ return [ '$description' => 'This event triggers when a provider is created.', ], 'delete' => [ - '$description' => 'This event triggers when a provider is deleted.' + '$description' => 'This event triggers when a provider is deleted.', ], 'subscribers' => [ '$model' => Response::MODEL_SUBSCRIBER, @@ -290,7 +290,7 @@ return [ '$description' => 'This event triggers when a subscriber is created.', ], 'delete' => [ - '$description' => 'This event triggers when a subscriber is deleted.' + '$description' => 'This event triggers when a subscriber is deleted.', ], ], ], diff --git a/app/config/locale/codes.php b/app/config/locale/codes.php index 641a2a6220..ed878887ca 100644 --- a/app/config/locale/codes.php +++ b/app/config/locale/codes.php @@ -6,532 +6,531 @@ * * Source: * https://www.andiamo.co.uk/resources/iso-language-codes/ - * */ return [ [ - "code" => "af", - "name" => "Afrikaans", + 'code' => 'af', + 'name' => 'Afrikaans', ], [ - "code" => "ar-ae", - "name" => "Arabic (U.A.E.)", + 'code' => 'ar-ae', + 'name' => 'Arabic (U.A.E.)', ], [ - "code" => "ar-bh", - "name" => "Arabic (Bahrain)", + 'code' => 'ar-bh', + 'name' => 'Arabic (Bahrain)', ], [ - "code" => "ar-dz", - "name" => "Arabic (Algeria)", + 'code' => 'ar-dz', + 'name' => 'Arabic (Algeria)', ], [ - "code" => "ar-eg", - "name" => "Arabic (Egypt)", + 'code' => 'ar-eg', + 'name' => 'Arabic (Egypt)', ], [ - "code" => "ar-iq", - "name" => "Arabic (Iraq)", + 'code' => 'ar-iq', + 'name' => 'Arabic (Iraq)', ], [ - "code" => "ar-jo", - "name" => "Arabic (Jordan)", + 'code' => 'ar-jo', + 'name' => 'Arabic (Jordan)', ], [ - "code" => "ar-kw", - "name" => "Arabic (Kuwait)", + 'code' => 'ar-kw', + 'name' => 'Arabic (Kuwait)', ], [ - "code" => "ar-lb", - "name" => "Arabic (Lebanon)", + 'code' => 'ar-lb', + 'name' => 'Arabic (Lebanon)', ], [ - "code" => "ar-ly", - "name" => "Arabic (Libya)", + 'code' => 'ar-ly', + 'name' => 'Arabic (Libya)', ], [ - "code" => "ar-ma", - "name" => "Arabic (Morocco)", + 'code' => 'ar-ma', + 'name' => 'Arabic (Morocco)', ], [ - "code" => "ar-om", - "name" => "Arabic (Oman)", + 'code' => 'ar-om', + 'name' => 'Arabic (Oman)', ], [ - "code" => "ar-qa", - "name" => "Arabic (Qatar)", + 'code' => 'ar-qa', + 'name' => 'Arabic (Qatar)', ], [ - "code" => "ar-sa", - "name" => "Arabic (Saudi Arabia)", + 'code' => 'ar-sa', + 'name' => 'Arabic (Saudi Arabia)', ], [ - "code" => "ar-sy", - "name" => "Arabic (Syria)", + 'code' => 'ar-sy', + 'name' => 'Arabic (Syria)', ], [ - "code" => "ar-tn", - "name" => "Arabic (Tunisia)", + 'code' => 'ar-tn', + 'name' => 'Arabic (Tunisia)', ], [ - "code" => "ar-ye", - "name" => "Arabic (Yemen)", + 'code' => 'ar-ye', + 'name' => 'Arabic (Yemen)', ], [ - "code" => "as", - "name" => "Assamese", + 'code' => 'as', + 'name' => 'Assamese', ], [ - "code" => "az", - "name" => "Azerbaijani", + 'code' => 'az', + 'name' => 'Azerbaijani', ], [ - "code" => "be", - "name" => "Belarusian", + 'code' => 'be', + 'name' => 'Belarusian', ], [ - "code" => "bg", - "name" => "Bulgarian", + 'code' => 'bg', + 'name' => 'Bulgarian', ], [ - "code" => "bh", - "name" => "Bihari", + 'code' => 'bh', + 'name' => 'Bihari', ], [ - "code" => "bn", - "name" => "Bengali", + 'code' => 'bn', + 'name' => 'Bengali', ], [ - "code" => "bs", - "name" => "Bosnian", + 'code' => 'bs', + 'name' => 'Bosnian', ], [ - "code" => "ca", - "name" => "Catalan", + 'code' => 'ca', + 'name' => 'Catalan', ], [ - "code" => "cs", - "name" => "Czech", + 'code' => 'cs', + 'name' => 'Czech', ], [ - "code" => "cy", - "name" => "Welsh", + 'code' => 'cy', + 'name' => 'Welsh', ], [ - "code" => "da", - "name" => "Danish", + 'code' => 'da', + 'name' => 'Danish', ], [ - "code" => "de", - "name" => "German (Standard)", + 'code' => 'de', + 'name' => 'German (Standard)', ], [ - "code" => "de-at", - "name" => "German (Austria)", + 'code' => 'de-at', + 'name' => 'German (Austria)', ], [ - "code" => "de-ch", - "name" => "German (Switzerland)", + 'code' => 'de-ch', + 'name' => 'German (Switzerland)', ], [ - "code" => "de-li", - "name" => "German (Liechtenstein)", + 'code' => 'de-li', + 'name' => 'German (Liechtenstein)', ], [ - "code" => "de-lu", - "name" => "German (Luxembourg)", + 'code' => 'de-lu', + 'name' => 'German (Luxembourg)', ], [ - "code" => "el", - "name" => "Greek", + 'code' => 'el', + 'name' => 'Greek', ], [ - "code" => "en", - "name" => "English", + 'code' => 'en', + 'name' => 'English', ], [ - "code" => "en-au", - "name" => "English (Australia)", + 'code' => 'en-au', + 'name' => 'English (Australia)', ], [ - "code" => "en-bz", - "name" => "English (Belize)", + 'code' => 'en-bz', + 'name' => 'English (Belize)', ], [ - "code" => "en-ca", - "name" => "English (Canada)", + 'code' => 'en-ca', + 'name' => 'English (Canada)', ], [ - "code" => "en-gb", - "name" => "English (United Kingdom)", + 'code' => 'en-gb', + 'name' => 'English (United Kingdom)', ], [ - "code" => "en-ie", - "name" => "English (Ireland)", + 'code' => 'en-ie', + 'name' => 'English (Ireland)', ], [ - "code" => "en-jm", - "name" => "English (Jamaica)", + 'code' => 'en-jm', + 'name' => 'English (Jamaica)', ], [ - "code" => "en-nz", - "name" => "English (New Zealand)", + 'code' => 'en-nz', + 'name' => 'English (New Zealand)', ], [ - "code" => "en-tt", - "name" => "English (Trinidad)", + 'code' => 'en-tt', + 'name' => 'English (Trinidad)', ], [ - "code" => "en-us", - "name" => "English (United States)", + 'code' => 'en-us', + 'name' => 'English (United States)', ], [ - "code" => "en-za", - "name" => "English (South Africa)", + 'code' => 'en-za', + 'name' => 'English (South Africa)', ], [ - "code" => "eo", - "name" => "Esperanto", + 'code' => 'eo', + 'name' => 'Esperanto', ], [ - "code" => "es", - "name" => "Spanish (Spain)", + 'code' => 'es', + 'name' => 'Spanish (Spain)', ], [ - "code" => "es-ar", - "name" => "Spanish (Argentina)", + 'code' => 'es-ar', + 'name' => 'Spanish (Argentina)', ], [ - "code" => "es-bo", - "name" => "Spanish (Bolivia)", + 'code' => 'es-bo', + 'name' => 'Spanish (Bolivia)', ], [ - "code" => "es-cl", - "name" => "Spanish (Chile)", + 'code' => 'es-cl', + 'name' => 'Spanish (Chile)', ], [ - "code" => "es-co", - "name" => "Spanish (Colombia)", + 'code' => 'es-co', + 'name' => 'Spanish (Colombia)', ], [ - "code" => "es-cr", - "name" => "Spanish (Costa Rica)", + 'code' => 'es-cr', + 'name' => 'Spanish (Costa Rica)', ], [ - "code" => "es-do", - "name" => "Spanish (Dominican Republic)", + 'code' => 'es-do', + 'name' => 'Spanish (Dominican Republic)', ], [ - "code" => "es-ec", - "name" => "Spanish (Ecuador)", + 'code' => 'es-ec', + 'name' => 'Spanish (Ecuador)', ], [ - "code" => "es-gt", - "name" => "Spanish (Guatemala)", + 'code' => 'es-gt', + 'name' => 'Spanish (Guatemala)', ], [ - "code" => "es-hn", - "name" => "Spanish (Honduras)", + 'code' => 'es-hn', + 'name' => 'Spanish (Honduras)', ], [ - "code" => "es-mx", - "name" => "Spanish (Mexico)", + 'code' => 'es-mx', + 'name' => 'Spanish (Mexico)', ], [ - "code" => "es-ni", - "name" => "Spanish (Nicaragua)", + 'code' => 'es-ni', + 'name' => 'Spanish (Nicaragua)', ], [ - "code" => "es-pa", - "name" => "Spanish (Panama)", + 'code' => 'es-pa', + 'name' => 'Spanish (Panama)', ], [ - "code" => "es-pe", - "name" => "Spanish (Peru)", + 'code' => 'es-pe', + 'name' => 'Spanish (Peru)', ], [ - "code" => "es-pr", - "name" => "Spanish (Puerto Rico)", + 'code' => 'es-pr', + 'name' => 'Spanish (Puerto Rico)', ], [ - "code" => "es-py", - "name" => "Spanish (Paraguay)", + 'code' => 'es-py', + 'name' => 'Spanish (Paraguay)', ], [ - "code" => "es-sv", - "name" => "Spanish (El Salvador)", + 'code' => 'es-sv', + 'name' => 'Spanish (El Salvador)', ], [ - "code" => "es-uy", - "name" => "Spanish (Uruguay)", + 'code' => 'es-uy', + 'name' => 'Spanish (Uruguay)', ], [ - "code" => "es-ve", - "name" => "Spanish (Venezuela)", + 'code' => 'es-ve', + 'name' => 'Spanish (Venezuela)', ], [ - "code" => "et", - "name" => "Estonian", + 'code' => 'et', + 'name' => 'Estonian', ], [ - "code" => "eu", - "name" => "Basque", + 'code' => 'eu', + 'name' => 'Basque', ], [ - "code" => "fa", - "name" => "Farsi", + 'code' => 'fa', + 'name' => 'Farsi', ], [ - "code" => "fi", - "name" => "Finnish", + 'code' => 'fi', + 'name' => 'Finnish', ], [ - "code" => "fo", - "name" => "Faeroese", + 'code' => 'fo', + 'name' => 'Faeroese', ], [ - "code" => "fr", - "name" => "French (Standard)", + 'code' => 'fr', + 'name' => 'French (Standard)', ], [ - "code" => "fr-be", - "name" => "French (Belgium)", + 'code' => 'fr-be', + 'name' => 'French (Belgium)', ], [ - "code" => "fr-ca", - "name" => "French (Canada)", + 'code' => 'fr-ca', + 'name' => 'French (Canada)', ], [ - "code" => "fr-ch", - "name" => "French (Switzerland)", + 'code' => 'fr-ch', + 'name' => 'French (Switzerland)', ], [ - "code" => "fr-lu", - "name" => "French (Luxembourg)", + 'code' => 'fr-lu', + 'name' => 'French (Luxembourg)', ], [ - "code" => "ga", - "name" => "Irish", + 'code' => 'ga', + 'name' => 'Irish', ], [ - "code" => "gd", - "name" => "Gaelic (Scotland)", + 'code' => 'gd', + 'name' => 'Gaelic (Scotland)', ], [ - "code" => "he", - "name" => "Hebrew", + 'code' => 'he', + 'name' => 'Hebrew', ], [ - "code" => "hi", - "name" => "Hindi", + 'code' => 'hi', + 'name' => 'Hindi', ], [ - "code" => "hr", - "name" => "Croatian", + 'code' => 'hr', + 'name' => 'Croatian', ], [ - "code" => "hu", - "name" => "Hungarian", + 'code' => 'hu', + 'name' => 'Hungarian', ], [ - "code" => "id", - "name" => "Indonesian", + 'code' => 'id', + 'name' => 'Indonesian', ], [ - "code" => "is", - "name" => "Icelandic", + 'code' => 'is', + 'name' => 'Icelandic', ], [ - "code" => "it", - "name" => "Italian (Standard)", + 'code' => 'it', + 'name' => 'Italian (Standard)', ], [ - "code" => "it-ch", - "name" => "Italian (Switzerland)", + 'code' => 'it-ch', + 'name' => 'Italian (Switzerland)', ], [ - "code" => "ja", - "name" => "Japanese", + 'code' => 'ja', + 'name' => 'Japanese', ], [ - "code" => "ji", - "name" => "Yiddish", + 'code' => 'ji', + 'name' => 'Yiddish', ], [ - "code" => "ko", - "name" => "Korean", + 'code' => 'ko', + 'name' => 'Korean', ], [ - "code" => "ku", - "name" => "Kurdish", + 'code' => 'ku', + 'name' => 'Kurdish', ], [ - "code" => "lt", - "name" => "Lithuanian", + 'code' => 'lt', + 'name' => 'Lithuanian', ], [ - "code" => "lv", - "name" => "Latvian", + 'code' => 'lv', + 'name' => 'Latvian', ], [ - "code" => "mk", - "name" => "Macedonian (FYROM)", + 'code' => 'mk', + 'name' => 'Macedonian (FYROM)', ], [ - "code" => "ml", - "name" => "Malayalam", + 'code' => 'ml', + 'name' => 'Malayalam', ], [ - "code" => "ms", - "name" => "Malaysian", + 'code' => 'ms', + 'name' => 'Malaysian', ], [ - "code" => "mt", - "name" => "Maltese", + 'code' => 'mt', + 'name' => 'Maltese', ], [ - "code" => "nb", - "name" => "Norwegian (Bokmål)", + 'code' => 'nb', + 'name' => 'Norwegian (Bokmål)', ], [ - "code" => "ne", - "name" => "Nepali", + 'code' => 'ne', + 'name' => 'Nepali', ], [ - "code" => "nl", - "name" => "Dutch (Standard)", + 'code' => 'nl', + 'name' => 'Dutch (Standard)', ], [ - "code" => "nl-be", - "name" => "Dutch (Belgium)", + 'code' => 'nl-be', + 'name' => 'Dutch (Belgium)', ], [ - "code" => "nn", - "name" => "Norwegian (Nynorsk)", + 'code' => 'nn', + 'name' => 'Norwegian (Nynorsk)', ], [ - "code" => "no", - "name" => "Norwegian", + 'code' => 'no', + 'name' => 'Norwegian', ], [ - "code" => "pa", - "name" => "Punjabi", + 'code' => 'pa', + 'name' => 'Punjabi', ], [ - "code" => "pl", - "name" => "Polish", + 'code' => 'pl', + 'name' => 'Polish', ], [ - "code" => "pt", - "name" => "Portuguese (Portugal)", + 'code' => 'pt', + 'name' => 'Portuguese (Portugal)', ], [ - "code" => "pt-br", - "name" => "Portuguese (Brazil)", + 'code' => 'pt-br', + 'name' => 'Portuguese (Brazil)', ], [ - "code" => "rm", - "name" => "Rhaeto-Romanic", + 'code' => 'rm', + 'name' => 'Rhaeto-Romanic', ], [ - "code" => "ro", - "name" => "Romanian", + 'code' => 'ro', + 'name' => 'Romanian', ], [ - "code" => "ro-md", - "name" => "Romanian (Republic of Moldova)", + 'code' => 'ro-md', + 'name' => 'Romanian (Republic of Moldova)', ], [ - "code" => "ru", - "name" => "Russian", + 'code' => 'ru', + 'name' => 'Russian', ], [ - "code" => "ru-md", - "name" => "Russian (Republic of Moldova)", + 'code' => 'ru-md', + 'name' => 'Russian (Republic of Moldova)', ], [ - "code" => "sb", - "name" => "Sorbian", + 'code' => 'sb', + 'name' => 'Sorbian', ], [ - "code" => "sk", - "name" => "Slovak", + 'code' => 'sk', + 'name' => 'Slovak', ], [ - "code" => "sl", - "name" => "Slovenian", + 'code' => 'sl', + 'name' => 'Slovenian', ], [ - "code" => "sq", - "name" => "Albanian", + 'code' => 'sq', + 'name' => 'Albanian', ], [ - "code" => "sr", - "name" => "Serbian", + 'code' => 'sr', + 'name' => 'Serbian', ], [ - "code" => "sv", - "name" => "Swedish", + 'code' => 'sv', + 'name' => 'Swedish', ], [ - "code" => "sv-fi", - "name" => "Swedish (Finland)", + 'code' => 'sv-fi', + 'name' => 'Swedish (Finland)', ], [ - "code" => "th", - "name" => "Thai", + 'code' => 'th', + 'name' => 'Thai', ], [ - "code" => "tn", - "name" => "Tswana", + 'code' => 'tn', + 'name' => 'Tswana', ], [ - "code" => "tr", - "name" => "Turkish", + 'code' => 'tr', + 'name' => 'Turkish', ], [ - "code" => "ts", - "name" => "Tsonga", + 'code' => 'ts', + 'name' => 'Tsonga', ], [ - "code" => "ua", - "name" => "Ukrainian", + 'code' => 'ua', + 'name' => 'Ukrainian', ], [ - "code" => "ur", - "name" => "Urdu", + 'code' => 'ur', + 'name' => 'Urdu', ], [ - "code" => "ve", - "name" => "Venda", + 'code' => 've', + 'name' => 'Venda', ], [ - "code" => "vi", - "name" => "Vietnamese", + 'code' => 'vi', + 'name' => 'Vietnamese', ], [ - "code" => "xh", - "name" => "Xhosa", + 'code' => 'xh', + 'name' => 'Xhosa', ], [ - "code" => "zh-cn", - "name" => "Chinese (PRC)", + 'code' => 'zh-cn', + 'name' => 'Chinese (PRC)', ], [ - "code" => "zh-hk", - "name" => "Chinese (Hong Kong)", + 'code' => 'zh-hk', + 'name' => 'Chinese (Hong Kong)', ], [ - "code" => "zh-sg", - "name" => "Chinese (Singapore)", + 'code' => 'zh-sg', + 'name' => 'Chinese (Singapore)', ], [ - "code" => "zh-tw", - "name" => "Chinese (Taiwan)", + 'code' => 'zh-tw', + 'name' => 'Chinese (Taiwan)', ], [ - "code" => "zu", - "name" => "Zulu", + 'code' => 'zu', + 'name' => 'Zulu', ], ]; diff --git a/app/config/locale/languages.php b/app/config/locale/languages.php index 6272bd02a6..318ec27492 100644 --- a/app/config/locale/languages.php +++ b/app/config/locale/languages.php @@ -9,923 +9,923 @@ return [ [ - "code" => "aa", - "name" => "Afar", - "nativeName" => "Afar" + 'code' => 'aa', + 'name' => 'Afar', + 'nativeName' => 'Afar', ], [ - "code" => "ab", - "name" => "Abkhazian", - "nativeName" => "Аҧсуа" + 'code' => 'ab', + 'name' => 'Abkhazian', + 'nativeName' => 'Аҧсуа', ], [ - "code" => "af", - "name" => "Afrikaans", - "nativeName" => "Afrikaans" + 'code' => 'af', + 'name' => 'Afrikaans', + 'nativeName' => 'Afrikaans', ], [ - "code" => "ak", - "name" => "Akan", - "nativeName" => "Akana" + 'code' => 'ak', + 'name' => 'Akan', + 'nativeName' => 'Akana', ], [ - "code" => "am", - "name" => "Amharic", - "nativeName" => "አማርኛ" + 'code' => 'am', + 'name' => 'Amharic', + 'nativeName' => 'አማርኛ', ], [ - "code" => "an", - "name" => "Aragonese", - "nativeName" => "Aragonés" + 'code' => 'an', + 'name' => 'Aragonese', + 'nativeName' => 'Aragonés', ], [ - "code" => "ar", - "name" => "Arabic", - "nativeName" => "العربية" + 'code' => 'ar', + 'name' => 'Arabic', + 'nativeName' => 'العربية', ], [ - "code" => "as", - "name" => "Assamese", - "nativeName" => "অসমীয়া" + 'code' => 'as', + 'name' => 'Assamese', + 'nativeName' => 'অসমীয়া', ], [ - "code" => "av", - "name" => "Avar", - "nativeName" => "Авар" + 'code' => 'av', + 'name' => 'Avar', + 'nativeName' => 'Авар', ], [ - "code" => "ay", - "name" => "Aymara", - "nativeName" => "Aymar" + 'code' => 'ay', + 'name' => 'Aymara', + 'nativeName' => 'Aymar', ], [ - "code" => "az", - "name" => "Azerbaijani", - "nativeName" => "Azərbaycanca / آذربايجان" + 'code' => 'az', + 'name' => 'Azerbaijani', + 'nativeName' => 'Azərbaycanca / آذربايجان', ], [ - "code" => "ba", - "name" => "Bashkir", - "nativeName" => "Башҡорт" + 'code' => 'ba', + 'name' => 'Bashkir', + 'nativeName' => 'Башҡорт', ], [ - "code" => "be", - "name" => "Belarusian", - "nativeName" => "Беларуская" + 'code' => 'be', + 'name' => 'Belarusian', + 'nativeName' => 'Беларуская', ], [ - "code" => "bg", - "name" => "Bulgarian", - "nativeName" => "Български" + 'code' => 'bg', + 'name' => 'Bulgarian', + 'nativeName' => 'Български', ], [ - "code" => "bh", - "name" => "Bihari", - "nativeName" => "भोजपुरी" + 'code' => 'bh', + 'name' => 'Bihari', + 'nativeName' => 'भोजपुरी', ], [ - "code" => "bi", - "name" => "Bislama", - "nativeName" => "Bislama" + 'code' => 'bi', + 'name' => 'Bislama', + 'nativeName' => 'Bislama', ], [ - "code" => "bm", - "name" => "Bambara", - "nativeName" => "Bamanankan" + 'code' => 'bm', + 'name' => 'Bambara', + 'nativeName' => 'Bamanankan', ], [ - "code" => "bn", - "name" => "Bengali", - "nativeName" => "বাংলা" + 'code' => 'bn', + 'name' => 'Bengali', + 'nativeName' => 'বাংলা', ], [ - "code" => "bo", - "name" => "Tibetan", - "nativeName" => "བོད་ཡིག / Bod skad" + 'code' => 'bo', + 'name' => 'Tibetan', + 'nativeName' => 'བོད་ཡིག / Bod skad', ], [ - "code" => "br", - "name" => "Breton", - "nativeName" => "Brezhoneg" + 'code' => 'br', + 'name' => 'Breton', + 'nativeName' => 'Brezhoneg', ], [ - "code" => "bs", - "name" => "Bosnian", - "nativeName" => "Bosanski" + 'code' => 'bs', + 'name' => 'Bosnian', + 'nativeName' => 'Bosanski', ], [ - "code" => "ca", - "name" => "Catalan", - "nativeName" => "Català" + 'code' => 'ca', + 'name' => 'Catalan', + 'nativeName' => 'Català', ], [ - "code" => "ce", - "name" => "Chechen", - "nativeName" => "Нохчийн" + 'code' => 'ce', + 'name' => 'Chechen', + 'nativeName' => 'Нохчийн', ], [ - "code" => "ch", - "name" => "Chamorro", - "nativeName" => "Chamoru" + 'code' => 'ch', + 'name' => 'Chamorro', + 'nativeName' => 'Chamoru', ], [ - "code" => "co", - "name" => "Corsican", - "nativeName" => "Corsu" + 'code' => 'co', + 'name' => 'Corsican', + 'nativeName' => 'Corsu', ], [ - "code" => "cr", - "name" => "Cree", - "nativeName" => "Nehiyaw" + 'code' => 'cr', + 'name' => 'Cree', + 'nativeName' => 'Nehiyaw', ], [ - "code" => "cs", - "name" => "Czech", - "nativeName" => "Česky" + 'code' => 'cs', + 'name' => 'Czech', + 'nativeName' => 'Česky', ], [ - "code" => "cu", - "name" => "Old Church Slavonic / Old Bulgarian", - "nativeName" => "словѣньскъ / slověnĭskŭ" + 'code' => 'cu', + 'name' => 'Old Church Slavonic / Old Bulgarian', + 'nativeName' => 'словѣньскъ / slověnĭskŭ', ], [ - "code" => "cv", - "name" => "Chuvash", - "nativeName" => "Чăваш" + 'code' => 'cv', + 'name' => 'Chuvash', + 'nativeName' => 'Чăваш', ], [ - "code" => "cy", - "name" => "Welsh", - "nativeName" => "Cymraeg" + 'code' => 'cy', + 'name' => 'Welsh', + 'nativeName' => 'Cymraeg', ], [ - "code" => "da", - "name" => "Danish", - "nativeName" => "Dansk" + 'code' => 'da', + 'name' => 'Danish', + 'nativeName' => 'Dansk', ], [ - "code" => "de", - "name" => "German", - "nativeName" => "Deutsch" + 'code' => 'de', + 'name' => 'German', + 'nativeName' => 'Deutsch', ], [ - "code" => "dv", - "name" => "Divehi", - "nativeName" => "ދިވެހިބަސް" + 'code' => 'dv', + 'name' => 'Divehi', + 'nativeName' => 'ދިވެހިބަސް', ], [ - "code" => "dz", - "name" => "Dzongkha", - "nativeName" => "ཇོང་ཁ" + 'code' => 'dz', + 'name' => 'Dzongkha', + 'nativeName' => 'ཇོང་ཁ', ], [ - "code" => "ee", - "name" => "Ewe", - "nativeName" => "Ɛʋɛ" + 'code' => 'ee', + 'name' => 'Ewe', + 'nativeName' => 'Ɛʋɛ', ], [ - "code" => "el", - "name" => "Greek", - "nativeName" => "Ελληνικά" + 'code' => 'el', + 'name' => 'Greek', + 'nativeName' => 'Ελληνικά', ], [ - "code" => "en", - "name" => "English", - "nativeName" => "English" + 'code' => 'en', + 'name' => 'English', + 'nativeName' => 'English', ], [ - "code" => "eo", - "name" => "Esperanto", - "nativeName" => "Esperanto" + 'code' => 'eo', + 'name' => 'Esperanto', + 'nativeName' => 'Esperanto', ], [ - "code" => "es", - "name" => "Spanish", - "nativeName" => "Español" + 'code' => 'es', + 'name' => 'Spanish', + 'nativeName' => 'Español', ], [ - "code" => "et", - "name" => "Estonian", - "nativeName" => "Eesti" + 'code' => 'et', + 'name' => 'Estonian', + 'nativeName' => 'Eesti', ], [ - "code" => "eu", - "name" => "Basque", - "nativeName" => "Euskara" + 'code' => 'eu', + 'name' => 'Basque', + 'nativeName' => 'Euskara', ], [ - "code" => "fa", - "name" => "Persian", - "nativeName" => "فارسی" + 'code' => 'fa', + 'name' => 'Persian', + 'nativeName' => 'فارسی', ], [ - "code" => "ff", - "name" => "Peul", - "nativeName" => "Fulfulde" + 'code' => 'ff', + 'name' => 'Peul', + 'nativeName' => 'Fulfulde', ], [ - "code" => "fi", - "name" => "Finnish", - "nativeName" => "Suomi" + 'code' => 'fi', + 'name' => 'Finnish', + 'nativeName' => 'Suomi', ], [ - "code" => "fj", - "name" => "Fijian", - "nativeName" => "Na Vosa Vakaviti" + 'code' => 'fj', + 'name' => 'Fijian', + 'nativeName' => 'Na Vosa Vakaviti', ], [ - "code" => "fo", - "name" => "Faroese", - "nativeName" => "Føroyskt" + 'code' => 'fo', + 'name' => 'Faroese', + 'nativeName' => 'Føroyskt', ], [ - "code" => "fr", - "name" => "French", - "nativeName" => "Français" + 'code' => 'fr', + 'name' => 'French', + 'nativeName' => 'Français', ], [ - "code" => "fy", - "name" => "West Frisian", - "nativeName" => "Frysk" + 'code' => 'fy', + 'name' => 'West Frisian', + 'nativeName' => 'Frysk', ], [ - "code" => "ga", - "name" => "Irish", - "nativeName" => "Gaeilge" + 'code' => 'ga', + 'name' => 'Irish', + 'nativeName' => 'Gaeilge', ], [ - "code" => "gd", - "name" => "Scottish Gaelic", - "nativeName" => "Gàidhlig" + 'code' => 'gd', + 'name' => 'Scottish Gaelic', + 'nativeName' => 'Gàidhlig', ], [ - "code" => "gl", - "name" => "Galician", - "nativeName" => "Galego" + 'code' => 'gl', + 'name' => 'Galician', + 'nativeName' => 'Galego', ], [ - "code" => "gn", - "name" => "Guarani", - "nativeName" => "Avañe'ẽ" + 'code' => 'gn', + 'name' => 'Guarani', + 'nativeName' => "Avañe'ẽ", ], [ - "code" => "gu", - "name" => "Gujarati", - "nativeName" => "ગુજરાતી" + 'code' => 'gu', + 'name' => 'Gujarati', + 'nativeName' => 'ગુજરાતી', ], [ - "code" => "gv", - "name" => "Manx", - "nativeName" => "Gaelg" + 'code' => 'gv', + 'name' => 'Manx', + 'nativeName' => 'Gaelg', ], [ - "code" => "ha", - "name" => "Hausa", - "nativeName" => "هَوُسَ" + 'code' => 'ha', + 'name' => 'Hausa', + 'nativeName' => 'هَوُسَ', ], [ - "code" => "he", - "name" => "Hebrew", - "nativeName" => "עברית" + 'code' => 'he', + 'name' => 'Hebrew', + 'nativeName' => 'עברית', ], [ - "code" => "hi", - "name" => "Hindi", - "nativeName" => "हिन्दी / हिंदी " + 'code' => 'hi', + 'name' => 'Hindi', + 'nativeName' => 'हिन्दी / हिंदी ', ], [ - "code" => "ho", - "name" => "Hiri Motu", - "nativeName" => "Hiri Motu" + 'code' => 'ho', + 'name' => 'Hiri Motu', + 'nativeName' => 'Hiri Motu', ], [ - "code" => "hr", - "name" => "Croatian", - "nativeName" => "Hrvatski" + 'code' => 'hr', + 'name' => 'Croatian', + 'nativeName' => 'Hrvatski', ], [ - "code" => "ht", - "name" => "Haitian", - "nativeName" => "Krèyol ayisyen" + 'code' => 'ht', + 'name' => 'Haitian', + 'nativeName' => 'Krèyol ayisyen', ], [ - "code" => "hu", - "name" => "Hungarian", - "nativeName" => "Magyar" + 'code' => 'hu', + 'name' => 'Hungarian', + 'nativeName' => 'Magyar', ], [ - "code" => "hy", - "name" => "Armenian", - "nativeName" => "Հայերեն" + 'code' => 'hy', + 'name' => 'Armenian', + 'nativeName' => 'Հայերեն', ], [ - "code" => "hz", - "name" => "Herero", - "nativeName" => "Otsiherero" + 'code' => 'hz', + 'name' => 'Herero', + 'nativeName' => 'Otsiherero', ], [ - "code" => "ia", - "name" => "Interlingua", - "nativeName" => "Interlingua" + 'code' => 'ia', + 'name' => 'Interlingua', + 'nativeName' => 'Interlingua', ], [ - "code" => "id", - "name" => "Indonesian", - "nativeName" => "Bahasa Indonesia" + 'code' => 'id', + 'name' => 'Indonesian', + 'nativeName' => 'Bahasa Indonesia', ], [ - "code" => "ie", - "name" => "Interlingue", - "nativeName" => "Interlingue" + 'code' => 'ie', + 'name' => 'Interlingue', + 'nativeName' => 'Interlingue', ], [ - "code" => "ig", - "name" => "Igbo", - "nativeName" => "Igbo" + 'code' => 'ig', + 'name' => 'Igbo', + 'nativeName' => 'Igbo', ], [ - "code" => "ii", - "name" => "Sichuan Yi", - "nativeName" => "ꆇꉙ / 四川彝语" + 'code' => 'ii', + 'name' => 'Sichuan Yi', + 'nativeName' => 'ꆇꉙ / 四川彝语', ], [ - "code" => "ik", - "name" => "Inupiak", - "nativeName" => "Iñupiak" + 'code' => 'ik', + 'name' => 'Inupiak', + 'nativeName' => 'Iñupiak', ], [ - "code" => "io", - "name" => "Ido", - "nativeName" => "Ido" + 'code' => 'io', + 'name' => 'Ido', + 'nativeName' => 'Ido', ], [ - "code" => "is", - "name" => "Icelandic", - "nativeName" => "Íslenska" + 'code' => 'is', + 'name' => 'Icelandic', + 'nativeName' => 'Íslenska', ], [ - "code" => "it", - "name" => "Italian", - "nativeName" => "Italiano" + 'code' => 'it', + 'name' => 'Italian', + 'nativeName' => 'Italiano', ], [ - "code" => "iu", - "name" => "Inuktitut", - "nativeName" => "ᐃᓄᒃᑎᑐᑦ" + 'code' => 'iu', + 'name' => 'Inuktitut', + 'nativeName' => 'ᐃᓄᒃᑎᑐᑦ', ], [ - "code" => "ja", - "name" => "Japanese", - "nativeName" => "日本語" + 'code' => 'ja', + 'name' => 'Japanese', + 'nativeName' => '日本語', ], [ - "code" => "jv", - "name" => "Javanese", - "nativeName" => "Basa Jawa" + 'code' => 'jv', + 'name' => 'Javanese', + 'nativeName' => 'Basa Jawa', ], [ - "code" => "ka", - "name" => "Georgian", - "nativeName" => "ქართული" + 'code' => 'ka', + 'name' => 'Georgian', + 'nativeName' => 'ქართული', ], [ - "code" => "kg", - "name" => "Kongo", - "nativeName" => "KiKongo" + 'code' => 'kg', + 'name' => 'Kongo', + 'nativeName' => 'KiKongo', ], [ - "code" => "ki", - "name" => "Kikuyu", - "nativeName" => "Gĩkũyũ" + 'code' => 'ki', + 'name' => 'Kikuyu', + 'nativeName' => 'Gĩkũyũ', ], [ - "code" => "kj", - "name" => "Kuanyama", - "nativeName" => "Kuanyama" + 'code' => 'kj', + 'name' => 'Kuanyama', + 'nativeName' => 'Kuanyama', ], [ - "code" => "kk", - "name" => "Kazakh", - "nativeName" => "Қазақша" + 'code' => 'kk', + 'name' => 'Kazakh', + 'nativeName' => 'Қазақша', ], [ - "code" => "kl", - "name" => "Greenlandic", - "nativeName" => "Kalaallisut" + 'code' => 'kl', + 'name' => 'Greenlandic', + 'nativeName' => 'Kalaallisut', ], [ - "code" => "km", - "name" => "Khmer", - "nativeName" => "ភាសាខ្មែរ" + 'code' => 'km', + 'name' => 'Khmer', + 'nativeName' => 'ភាសាខ្មែរ', ], [ - "code" => "kn", - "name" => "Kannada", - "nativeName" => "ಕನ್ನಡ" + 'code' => 'kn', + 'name' => 'Kannada', + 'nativeName' => 'ಕನ್ನಡ', ], [ - "code" => "ko", - "name" => "Korean", - "nativeName" => "한국어" + 'code' => 'ko', + 'name' => 'Korean', + 'nativeName' => '한국어', ], [ - "code" => "kr", - "name" => "Kanuri", - "nativeName" => "Kanuri" + 'code' => 'kr', + 'name' => 'Kanuri', + 'nativeName' => 'Kanuri', ], [ - "code" => "ks", - "name" => "Kashmiri", - "nativeName" => "कश्मीरी / كشميري" + 'code' => 'ks', + 'name' => 'Kashmiri', + 'nativeName' => 'कश्मीरी / كشميري', ], [ - "code" => "ku", - "name" => "Kurdish", - "nativeName" => "Kurdî / كوردی" + 'code' => 'ku', + 'name' => 'Kurdish', + 'nativeName' => 'Kurdî / كوردی', ], [ - "code" => "kv", - "name" => "Komi", - "nativeName" => "Коми" + 'code' => 'kv', + 'name' => 'Komi', + 'nativeName' => 'Коми', ], [ - "code" => "kw", - "name" => "Cornish", - "nativeName" => "Kernewek" + 'code' => 'kw', + 'name' => 'Cornish', + 'nativeName' => 'Kernewek', ], [ - "code" => "ky", - "name" => "Kirghiz", - "nativeName" => "Kırgızca / Кыргызча" + 'code' => 'ky', + 'name' => 'Kirghiz', + 'nativeName' => 'Kırgızca / Кыргызча', ], [ - "code" => "la", - "name" => "Latin", - "nativeName" => "Latina" + 'code' => 'la', + 'name' => 'Latin', + 'nativeName' => 'Latina', ], [ - "code" => "lb", - "name" => "Luxembourgish", - "nativeName" => "Lëtzebuergesch" + 'code' => 'lb', + 'name' => 'Luxembourgish', + 'nativeName' => 'Lëtzebuergesch', ], [ - "code" => "lg", - "name" => "Ganda", - "nativeName" => "Luganda" + 'code' => 'lg', + 'name' => 'Ganda', + 'nativeName' => 'Luganda', ], [ - "code" => "li", - "name" => "Limburgian", - "nativeName" => "Limburgs" + 'code' => 'li', + 'name' => 'Limburgian', + 'nativeName' => 'Limburgs', ], [ - "code" => "ln", - "name" => "Lingala", - "nativeName" => "Lingála" + 'code' => 'ln', + 'name' => 'Lingala', + 'nativeName' => 'Lingála', ], [ - "code" => "lo", - "name" => "Laotian", - "nativeName" => "ລາວ / Pha xa lao" + 'code' => 'lo', + 'name' => 'Laotian', + 'nativeName' => 'ລາວ / Pha xa lao', ], [ - "code" => "lt", - "name" => "Lithuanian", - "nativeName" => "Lietuvių" + 'code' => 'lt', + 'name' => 'Lithuanian', + 'nativeName' => 'Lietuvių', ], [ - "code" => "lu", - "name" => "Luba-Katanga", - "nativeName" => "Tshiluba" + 'code' => 'lu', + 'name' => 'Luba-Katanga', + 'nativeName' => 'Tshiluba', ], [ - "code" => "lv", - "name" => "Latvian", - "nativeName" => "Latviešu" + 'code' => 'lv', + 'name' => 'Latvian', + 'nativeName' => 'Latviešu', ], [ - "code" => "mg", - "name" => "Malagasy", - "nativeName" => "Malagasy" + 'code' => 'mg', + 'name' => 'Malagasy', + 'nativeName' => 'Malagasy', ], [ - "code" => "mh", - "name" => "Marshallese", - "nativeName" => "Kajin Majel / Ebon" + 'code' => 'mh', + 'name' => 'Marshallese', + 'nativeName' => 'Kajin Majel / Ebon', ], [ - "code" => "mi", - "name" => "Maori", - "nativeName" => "Māori" + 'code' => 'mi', + 'name' => 'Maori', + 'nativeName' => 'Māori', ], [ - "code" => "mk", - "name" => "Macedonian", - "nativeName" => "Македонски" + 'code' => 'mk', + 'name' => 'Macedonian', + 'nativeName' => 'Македонски', ], [ - "code" => "ml", - "name" => "Malayalam", - "nativeName" => "മലയാളം" + 'code' => 'ml', + 'name' => 'Malayalam', + 'nativeName' => 'മലയാളം', ], [ - "code" => "mn", - "name" => "Mongolian", - "nativeName" => "Монгол" + 'code' => 'mn', + 'name' => 'Mongolian', + 'nativeName' => 'Монгол', ], [ - "code" => "mo", - "name" => "Moldovan", - "nativeName" => "Moldovenească" + 'code' => 'mo', + 'name' => 'Moldovan', + 'nativeName' => 'Moldovenească', ], [ - "code" => "mr", - "name" => "Marathi", - "nativeName" => "मराठी" + 'code' => 'mr', + 'name' => 'Marathi', + 'nativeName' => 'मराठी', ], [ - "code" => "ms", - "name" => "Malay", - "nativeName" => "Bahasa Melayu" + 'code' => 'ms', + 'name' => 'Malay', + 'nativeName' => 'Bahasa Melayu', ], [ - "code" => "mt", - "name" => "Maltese", - "nativeName" => "bil-Malti" + 'code' => 'mt', + 'name' => 'Maltese', + 'nativeName' => 'bil-Malti', ], [ - "code" => "my", - "name" => "Burmese", - "nativeName" => "မြန်မာစာ" + 'code' => 'my', + 'name' => 'Burmese', + 'nativeName' => 'မြန်မာစာ', ], [ - "code" => "na", - "name" => "Nauruan", - "nativeName" => "Dorerin Naoero" + 'code' => 'na', + 'name' => 'Nauruan', + 'nativeName' => 'Dorerin Naoero', ], [ - "code" => "nb", - "name" => "Norwegian Bokmål", - "nativeName" => "Norsk bokmål" + 'code' => 'nb', + 'name' => 'Norwegian Bokmål', + 'nativeName' => 'Norsk bokmål', ], [ - "code" => "nd", - "name" => "North Ndebele", - "nativeName" => "Sindebele" + 'code' => 'nd', + 'name' => 'North Ndebele', + 'nativeName' => 'Sindebele', ], [ - "code" => "ne", - "name" => "Nepali", - "nativeName" => "नेपाली" + 'code' => 'ne', + 'name' => 'Nepali', + 'nativeName' => 'नेपाली', ], [ - "code" => "ng", - "name" => "Ndonga", - "nativeName" => "Oshiwambo" + 'code' => 'ng', + 'name' => 'Ndonga', + 'nativeName' => 'Oshiwambo', ], [ - "code" => "nl", - "name" => "Dutch", - "nativeName" => "Nederlands" + 'code' => 'nl', + 'name' => 'Dutch', + 'nativeName' => 'Nederlands', ], [ - "code" => "nn", - "name" => "Norwegian Nynorsk", - "nativeName" => "Norsk nynorsk" + 'code' => 'nn', + 'name' => 'Norwegian Nynorsk', + 'nativeName' => 'Norsk nynorsk', ], [ - "code" => "nr", - "name" => "South Ndebele", - "nativeName" => "isiNdebele" + 'code' => 'nr', + 'name' => 'South Ndebele', + 'nativeName' => 'isiNdebele', ], [ - "code" => "nv", - "name" => "Navajo", - "nativeName" => "Diné bizaad" + 'code' => 'nv', + 'name' => 'Navajo', + 'nativeName' => 'Diné bizaad', ], [ - "code" => "ny", - "name" => "Chichewa", - "nativeName" => "Chi-Chewa" + 'code' => 'ny', + 'name' => 'Chichewa', + 'nativeName' => 'Chi-Chewa', ], [ - "code" => "oc", - "name" => "Occitan", - "nativeName" => "Occitan" + 'code' => 'oc', + 'name' => 'Occitan', + 'nativeName' => 'Occitan', ], [ - "code" => "oj", - "name" => "Ojibwa", - "nativeName" => "ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin" + 'code' => 'oj', + 'name' => 'Ojibwa', + 'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin', ], [ - "code" => "om", - "name" => "Oromo", - "nativeName" => "Oromoo" + 'code' => 'om', + 'name' => 'Oromo', + 'nativeName' => 'Oromoo', ], [ - "code" => "or", - "name" => "Oriya", - "nativeName" => "ଓଡ଼ିଆ" + 'code' => 'or', + 'name' => 'Oriya', + 'nativeName' => 'ଓଡ଼ିଆ', ], [ - "code" => "os", - "name" => "Ossetian / Ossetic", - "nativeName" => "Иронау" + 'code' => 'os', + 'name' => 'Ossetian / Ossetic', + 'nativeName' => 'Иронау', ], [ - "code" => "pa", - "name" => "Panjabi / Punjabi", - "nativeName" => "ਪੰਜਾਬੀ / पंजाबी / پنجابي" + 'code' => 'pa', + 'name' => 'Panjabi / Punjabi', + 'nativeName' => 'ਪੰਜਾਬੀ / पंजाबी / پنجابي', ], [ - "code" => "pi", - "name" => "Pali", - "nativeName" => "Pāli / पाऴि" + 'code' => 'pi', + 'name' => 'Pali', + 'nativeName' => 'Pāli / पाऴि', ], [ - "code" => "pl", - "name" => "Polish", - "nativeName" => "Polski" + 'code' => 'pl', + 'name' => 'Polish', + 'nativeName' => 'Polski', ], [ - "code" => "ps", - "name" => "Pashto", - "nativeName" => "پښتو" + 'code' => 'ps', + 'name' => 'Pashto', + 'nativeName' => 'پښتو', ], [ - "code" => "pt", - "name" => "Portuguese", - "nativeName" => "Português" + 'code' => 'pt', + 'name' => 'Portuguese', + 'nativeName' => 'Português', ], [ - "code" => "qu", - "name" => "Quechua", - "nativeName" => "Runa Simi" + 'code' => 'qu', + 'name' => 'Quechua', + 'nativeName' => 'Runa Simi', ], [ - "code" => "rm", - "name" => "Raeto Romance", - "nativeName" => "Rumantsch" + 'code' => 'rm', + 'name' => 'Raeto Romance', + 'nativeName' => 'Rumantsch', ], [ - "code" => "rn", - "name" => "Kirundi", - "nativeName" => "Kirundi" + 'code' => 'rn', + 'name' => 'Kirundi', + 'nativeName' => 'Kirundi', ], [ - "code" => "ro", - "name" => "Romanian", - "nativeName" => "Română" + 'code' => 'ro', + 'name' => 'Romanian', + 'nativeName' => 'Română', ], [ - "code" => "ru", - "name" => "Russian", - "nativeName" => "Русский" + 'code' => 'ru', + 'name' => 'Russian', + 'nativeName' => 'Русский', ], [ - "code" => "rw", - "name" => "Rwandi", - "nativeName" => "Kinyarwandi" + 'code' => 'rw', + 'name' => 'Rwandi', + 'nativeName' => 'Kinyarwandi', ], [ - "code" => "sa", - "name" => "Sanskrit", - "nativeName" => "संस्कृतम्" + 'code' => 'sa', + 'name' => 'Sanskrit', + 'nativeName' => 'संस्कृतम्', ], [ - "code" => "sc", - "name" => "Sardinian", - "nativeName" => "Sardu" + 'code' => 'sc', + 'name' => 'Sardinian', + 'nativeName' => 'Sardu', ], [ - "code" => "sd", - "name" => "Sindhi", - "nativeName" => "सिन्धी / सिंधी " + 'code' => 'sd', + 'name' => 'Sindhi', + 'nativeName' => 'सिन्धी / सिंधी ', ], [ - "code" => "se", - "name" => "Northern Sami", - "nativeName" => "Sámegiella" + 'code' => 'se', + 'name' => 'Northern Sami', + 'nativeName' => 'Sámegiella', ], [ - "code" => "sg", - "name" => "Sango", - "nativeName" => "Sängö" + 'code' => 'sg', + 'name' => 'Sango', + 'nativeName' => 'Sängö', ], [ - "code" => "sh", - "name" => "Serbo-Croatian", - "nativeName" => "Srpskohrvatski / Српскохрватски" + 'code' => 'sh', + 'name' => 'Serbo-Croatian', + 'nativeName' => 'Srpskohrvatski / Српскохрватски', ], [ - "code" => "si", - "name" => "Sinhalese", - "nativeName" => "සිංහල" + 'code' => 'si', + 'name' => 'Sinhalese', + 'nativeName' => 'සිංහල', ], [ - "code" => "sk", - "name" => "Slovak", - "nativeName" => "Slovenčina" + 'code' => 'sk', + 'name' => 'Slovak', + 'nativeName' => 'Slovenčina', ], [ - "code" => "sl", - "name" => "Slovenian", - "nativeName" => "Slovenščina" + 'code' => 'sl', + 'name' => 'Slovenian', + 'nativeName' => 'Slovenščina', ], [ - "code" => "sm", - "name" => "Samoan", - "nativeName" => "Gagana Samoa" + 'code' => 'sm', + 'name' => 'Samoan', + 'nativeName' => 'Gagana Samoa', ], [ - "code" => "sn", - "name" => "Shona", - "nativeName" => "chiShona" + 'code' => 'sn', + 'name' => 'Shona', + 'nativeName' => 'chiShona', ], [ - "code" => "so", - "name" => "Somalia", - "nativeName" => "Soomaaliga" + 'code' => 'so', + 'name' => 'Somalia', + 'nativeName' => 'Soomaaliga', ], [ - "code" => "sq", - "name" => "Albanian", - "nativeName" => "Shqip" + 'code' => 'sq', + 'name' => 'Albanian', + 'nativeName' => 'Shqip', ], [ - "code" => "sr", - "name" => "Serbian", - "nativeName" => "Српски" + 'code' => 'sr', + 'name' => 'Serbian', + 'nativeName' => 'Српски', ], [ - "code" => "ss", - "name" => "Swati", - "nativeName" => "SiSwati" + 'code' => 'ss', + 'name' => 'Swati', + 'nativeName' => 'SiSwati', ], [ - "code" => "st", - "name" => "Southern Sotho", - "nativeName" => "Sesotho" + 'code' => 'st', + 'name' => 'Southern Sotho', + 'nativeName' => 'Sesotho', ], [ - "code" => "su", - "name" => "Sundanese", - "nativeName" => "Basa Sunda" + 'code' => 'su', + 'name' => 'Sundanese', + 'nativeName' => 'Basa Sunda', ], [ - "code" => "sv", - "name" => "Swedish", - "nativeName" => "Svenska" + 'code' => 'sv', + 'name' => 'Swedish', + 'nativeName' => 'Svenska', ], [ - "code" => "sw", - "name" => "Swahili", - "nativeName" => "Kiswahili" + 'code' => 'sw', + 'name' => 'Swahili', + 'nativeName' => 'Kiswahili', ], [ - "code" => "ta", - "name" => "Tamil", - "nativeName" => "தமிழ்" + 'code' => 'ta', + 'name' => 'Tamil', + 'nativeName' => 'தமிழ்', ], [ - "code" => "te", - "name" => "Telugu", - "nativeName" => "తెలుగు" + 'code' => 'te', + 'name' => 'Telugu', + 'nativeName' => 'తెలుగు', ], [ - "code" => "tg", - "name" => "Tajik", - "nativeName" => "Тоҷикӣ" + 'code' => 'tg', + 'name' => 'Tajik', + 'nativeName' => 'Тоҷикӣ', ], [ - "code" => "th", - "name" => "Thai", - "nativeName" => "ไทย / Phasa Thai" + 'code' => 'th', + 'name' => 'Thai', + 'nativeName' => 'ไทย / Phasa Thai', ], [ - "code" => "ti", - "name" => "Tigrinya", - "nativeName" => "ትግርኛ" + 'code' => 'ti', + 'name' => 'Tigrinya', + 'nativeName' => 'ትግርኛ', ], [ - "code" => "tk", - "name" => "Turkmen", - "nativeName" => "Туркмен / تركمن" + 'code' => 'tk', + 'name' => 'Turkmen', + 'nativeName' => 'Туркмен / تركمن', ], [ - "code" => "tl", - "name" => "Tagalog / Filipino", - "nativeName" => "Tagalog" + 'code' => 'tl', + 'name' => 'Tagalog / Filipino', + 'nativeName' => 'Tagalog', ], [ - "code" => "tn", - "name" => "Tswana", - "nativeName" => "Setswana" + 'code' => 'tn', + 'name' => 'Tswana', + 'nativeName' => 'Setswana', ], [ - "code" => "to", - "name" => "Tonga", - "nativeName" => "Lea Faka-Tonga" + 'code' => 'to', + 'name' => 'Tonga', + 'nativeName' => 'Lea Faka-Tonga', ], [ - "code" => "tr", - "name" => "Turkish", - "nativeName" => "Türkçe" + 'code' => 'tr', + 'name' => 'Turkish', + 'nativeName' => 'Türkçe', ], [ - "code" => "ts", - "name" => "Tsonga", - "nativeName" => "Xitsonga" + 'code' => 'ts', + 'name' => 'Tsonga', + 'nativeName' => 'Xitsonga', ], [ - "code" => "tt", - "name" => "Tatar", - "nativeName" => "Tatarça" + 'code' => 'tt', + 'name' => 'Tatar', + 'nativeName' => 'Tatarça', ], [ - "code" => "tw", - "name" => "Twi", - "nativeName" => "Twi" + 'code' => 'tw', + 'name' => 'Twi', + 'nativeName' => 'Twi', ], [ - "code" => "ty", - "name" => "Tahitian", - "nativeName" => "Reo Mā`ohi" + 'code' => 'ty', + 'name' => 'Tahitian', + 'nativeName' => 'Reo Mā`ohi', ], [ - "code" => "ug", - "name" => "Uyghur", - "nativeName" => "Uyƣurqə / ئۇيغۇرچە" + 'code' => 'ug', + 'name' => 'Uyghur', + 'nativeName' => 'Uyƣurqə / ئۇيغۇرچە', ], [ - "code" => "uk", - "name" => "Ukrainian", - "nativeName" => "Українська" + 'code' => 'uk', + 'name' => 'Ukrainian', + 'nativeName' => 'Українська', ], [ - "code" => "ur", - "name" => "Urdu", - "nativeName" => "اردو" + 'code' => 'ur', + 'name' => 'Urdu', + 'nativeName' => 'اردو', ], [ - "code" => "uz", - "name" => "Uzbek", - "nativeName" => "Ўзбек" + 'code' => 'uz', + 'name' => 'Uzbek', + 'nativeName' => 'Ўзбек', ], [ - "code" => "ve", - "name" => "Venda", - "nativeName" => "Tshivenḓa" + 'code' => 've', + 'name' => 'Venda', + 'nativeName' => 'Tshivenḓa', ], [ - "code" => "vi", - "name" => "Vietnamese", - "nativeName" => "Tiếng Việt" + 'code' => 'vi', + 'name' => 'Vietnamese', + 'nativeName' => 'Tiếng Việt', ], [ - "code" => "vo", - "name" => "Volapük", - "nativeName" => "Volapük" + 'code' => 'vo', + 'name' => 'Volapük', + 'nativeName' => 'Volapük', ], [ - "code" => "wa", - "name" => "Walloon", - "nativeName" => "Walon" + 'code' => 'wa', + 'name' => 'Walloon', + 'nativeName' => 'Walon', ], [ - "code" => "wo", - "name" => "Wolof", - "nativeName" => "Wollof" + 'code' => 'wo', + 'name' => 'Wolof', + 'nativeName' => 'Wollof', ], [ - "code" => "xh", - "name" => "Xhosa", - "nativeName" => "isiXhosa" + 'code' => 'xh', + 'name' => 'Xhosa', + 'nativeName' => 'isiXhosa', ], [ - "code" => "yi", - "name" => "Yiddish", - "nativeName" => "ייִדיש" + 'code' => 'yi', + 'name' => 'Yiddish', + 'nativeName' => 'ייִדיש', ], [ - "code" => "yo", - "name" => "Yoruba", - "nativeName" => "Yorùbá" + 'code' => 'yo', + 'name' => 'Yoruba', + 'nativeName' => 'Yorùbá', ], [ - "code" => "za", - "name" => "Zhuang", - "nativeName" => "Cuengh / Tôô / 壮语" + 'code' => 'za', + 'name' => 'Zhuang', + 'nativeName' => 'Cuengh / Tôô / 壮语', ], [ - "code" => "zh", - "name" => "Chinese", - "nativeName" => "中文" + 'code' => 'zh', + 'name' => 'Chinese', + 'nativeName' => '中文', ], [ - "code" => "zu", - "name" => "Zulu", - "nativeName" => "isiZulu" - ] + 'code' => 'zu', + 'name' => 'Zulu', + 'nativeName' => 'isiZulu', + ], ]; diff --git a/app/config/locale/templates.php b/app/config/locale/templates.php index f2672c04a0..9c365813a7 100644 --- a/app/config/locale/templates.php +++ b/app/config/locale/templates.php @@ -10,6 +10,6 @@ return [ 'sms' => [ 'verification', 'login', - 'invitation' - ] + 'invitation', + ], ]; diff --git a/app/config/messagingProviders.php b/app/config/messagingProviders.php index a33665196b..1d3ba8ed60 100644 --- a/app/config/messagingProviders.php +++ b/app/config/messagingProviders.php @@ -1,300 +1,300 @@ [ - 'mailchimp' => [ - 'name' => 'Mailchimp', - 'developers' => 'https://mailchimp.com/developer/marketing/api/', - 'icon' => 'icon-mailchimp', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, + 'email' => [ + 'mailchimp' => [ + 'name' => 'Mailchimp', + 'developers' => 'https://mailchimp.com/developer/marketing/api/', + 'icon' => 'icon-mailchimp', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'mailgun' => [ + 'name' => 'Mailgun', + 'developers' => 'https://documentation.mailgun.com/', + 'icon' => 'icon-mailgun', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'mailjet' => [ + 'name' => 'Mailjet', + 'developers' => 'https://dev.mailjet.com/', + 'icon' => 'icon-mailjet', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'postmark' => [ + 'name' => 'Postmark', + 'developers' => 'https://postmarkapp.com/developer', + 'icon' => 'icon-postmark', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sendgrid' => [ + 'name' => 'Sendgrid', + 'developers' => 'https://docs.sendgrid.com/api-reference/how-to-use-the-sendgrid-v3-api/', + 'icon' => 'icon-sendgrid', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sendinblue' => [ + 'name' => 'SendinBlue', + 'developers' => 'https://developers.sendinblue.com/', + 'icon' => 'icon-sendinblue', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'mailslurp' => [ + 'name' => 'MailSlurp', + 'developers' => 'https://www.mailslurp.com/docs/', + 'icon' => 'icon-mailslurp', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'elasticemail' => [ + 'name' => 'ElasticEmail', + 'developers' => 'https://api.elasticemail.com/public/help', + 'icon' => 'icon-elasticemail', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'ses' => [ + 'name' => 'SES', + 'developers' => 'https://docs.aws.amazon.com/ses/latest/APIReference/', + 'icon' => 'icon-ses', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], ], - 'mailgun' => [ - 'name' => 'Mailgun', - 'developers' => 'https://documentation.mailgun.com/', - 'icon' => 'icon-mailgun', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, + 'sms' => [ + 'africastalking' => [ + 'name' => 'Africa\'s Talking', + 'developers' => 'https://developers.africastalking.com/', + 'icon' => 'icon-africastalking', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'clickatell' => [ + 'name' => 'Clickatell', + 'developers' => 'https://www.clickatell.com/developers/api-docs/', + 'icon' => 'icon-clickatell', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'infobip' => [ + 'name' => 'Infobip', + 'developers' => 'https://www.infobip.com/docs/', + 'icon' => 'icon-infobip', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'msg91' => [ + 'name' => 'Msg91', + 'developers' => 'https://docs.msg91.com/reference/overview', + 'icon' => 'icon-msg91', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'plivo' => [ + 'name' => 'Plivo', + 'developers' => 'https://developers.plivo.com/', + 'icon' => 'icon-plivo', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sinch' => [ + 'name' => 'Sinch', + 'developers' => 'https://developers.sinch.com/', + 'icon' => 'icon-sinch', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sms77' => [ + 'name' => 'Sms77', + 'developers' => 'https://sms77.io/docs/gateway/', + 'icon' => 'icon-sms77', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'telesign' => [ + 'name' => 'Telesign', + 'developers' => 'https://developer.telesign.com/enterprise/docs', + 'icon' => 'icon-telesign', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'textmagic' => [ + 'name' => 'TextMagic', + 'developers' => 'https://www.textmagic.com/docs/api/', + 'icon' => 'icon-twilio', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'twilio' => [ + 'name' => 'Twilio', + 'developers' => 'https://www.twilio.com/docs/sms', + 'icon' => 'icon-twilio', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'twilio-notify' => [ + 'name' => 'Twilio Notify', + 'developers' => 'https://www.twilio.com/docs/notify', + 'icon' => 'icon-twilio', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'vonage' => [ + 'name' => 'Vonage', + 'developers' => 'https://developer.nexmo.com/', + 'icon' => 'icon-vonage', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], ], - 'mailjet' => [ - 'name' => 'Mailjet', - 'developers' => 'https://dev.mailjet.com/', - 'icon' => 'icon-mailjet', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, + 'push' => [ + 'apns' => [ + 'name' => 'APNS', + 'developers' => 'https://developer.apple.com/documentation/usernotifications', + 'icon' => 'icon-apns', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'fcm' => [ + 'name' => 'FCM', + 'developers' => 'https://firebase.google.com/docs/cloud-messaging', + 'icon' => 'icon-fcm', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'one_signal' => [ + 'name' => 'OneSignal', + 'developers' => 'https://documentation.onesignal.com/docs', + 'icon' => 'icon-onesignal', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'pushbullet' => [ + 'name' => 'PushBullet', + 'developers' => 'https://docs.pushbullet.com/', + 'icon' => 'icon-pushbullet', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'pusher' => [ + 'name' => 'Pusher', + 'developers' => 'https://pusher.com/docs', + 'icon' => 'icon-pusher', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'pushwoosh' => [ + 'name' => 'Pushwoosh', + 'developers' => 'https://www.pushwoosh.com/docs/', + 'icon' => 'icon-pushwoosh', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'urban_airship' => [ + 'name' => 'Urban Airship', + 'developers' => 'https://docs.airship.com/api/', + 'icon' => 'icon-urbanairship', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'web_push' => [ + 'name' => 'WebPush', + 'developers' => 'https://developer.mozilla.org/en-US/docs/Web/API/Push_API', + 'icon' => 'icon-webpush', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], ], - 'postmark' => [ - 'name' => 'Postmark', - 'developers' => 'https://postmarkapp.com/developer', - 'icon' => 'icon-postmark', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sendgrid' => [ - 'name' => 'Sendgrid', - 'developers' => 'https://docs.sendgrid.com/api-reference/how-to-use-the-sendgrid-v3-api/', - 'icon' => 'icon-sendgrid', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sendinblue' => [ - 'name' => 'SendinBlue', - 'developers' => 'https://developers.sendinblue.com/', - 'icon' => 'icon-sendinblue', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'mailslurp' => [ - 'name' => 'MailSlurp', - 'developers' => 'https://www.mailslurp.com/docs/', - 'icon' => 'icon-mailslurp', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'elasticemail' => [ - 'name' => 'ElasticEmail', - 'developers' => 'https://api.elasticemail.com/public/help', - 'icon' => 'icon-elasticemail', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'ses' => [ - 'name' => 'SES', - 'developers' => 'https://docs.aws.amazon.com/ses/latest/APIReference/', - 'icon' => 'icon-ses', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - ], - 'sms' => [ - 'africastalking' => [ - 'name' => 'Africa\'s Talking', - 'developers' => 'https://developers.africastalking.com/', - 'icon' => 'icon-africastalking', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'clickatell' => [ - 'name' => 'Clickatell', - 'developers' => 'https://www.clickatell.com/developers/api-docs/', - 'icon' => 'icon-clickatell', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'infobip' => [ - 'name' => 'Infobip', - 'developers' => 'https://www.infobip.com/docs/', - 'icon' => 'icon-infobip', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'msg91' => [ - 'name' => 'Msg91', - 'developers' => 'https://docs.msg91.com/reference/overview', - 'icon' => 'icon-msg91', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'plivo' => [ - 'name' => 'Plivo', - 'developers' => 'https://developers.plivo.com/', - 'icon' => 'icon-plivo', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sinch' => [ - 'name' => 'Sinch', - 'developers' => 'https://developers.sinch.com/', - 'icon' => 'icon-sinch', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sms77' => [ - 'name' => 'Sms77', - 'developers' => 'https://sms77.io/docs/gateway/', - 'icon' => 'icon-sms77', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'telesign' => [ - 'name' => 'Telesign', - 'developers' => 'https://developer.telesign.com/enterprise/docs', - 'icon' => 'icon-telesign', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'textmagic' => [ - 'name' => 'TextMagic', - 'developers' => 'https://www.textmagic.com/docs/api/', - 'icon' => 'icon-twilio', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'twilio' => [ - 'name' => 'Twilio', - 'developers' => 'https://www.twilio.com/docs/sms', - 'icon' => 'icon-twilio', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'twilio-notify' => [ - 'name' => 'Twilio Notify', - 'developers' => 'https://www.twilio.com/docs/notify', - 'icon' => 'icon-twilio', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'vonage' => [ - 'name' => 'Vonage', - 'developers' => 'https://developer.nexmo.com/', - 'icon' => 'icon-vonage', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - ], - 'push' => [ - 'apns' => [ - 'name' => 'APNS', - 'developers' => 'https://developer.apple.com/documentation/usernotifications', - 'icon' => 'icon-apns', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'fcm' => [ - 'name' => 'FCM', - 'developers' => 'https://firebase.google.com/docs/cloud-messaging', - 'icon' => 'icon-fcm', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'one_signal' => [ - 'name' => 'OneSignal', - 'developers' => 'https://documentation.onesignal.com/docs', - 'icon' => 'icon-onesignal', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'pushbullet' => [ - 'name' => 'PushBullet', - 'developers' => 'https://docs.pushbullet.com/', - 'icon' => 'icon-pushbullet', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'pusher' => [ - 'name' => 'Pusher', - 'developers' => 'https://pusher.com/docs', - 'icon' => 'icon-pusher', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'pushwoosh' => [ - 'name' => 'Pushwoosh', - 'developers' => 'https://www.pushwoosh.com/docs/', - 'icon' => 'icon-pushwoosh', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'urban_airship' => [ - 'name' => 'Urban Airship', - 'developers' => 'https://docs.airship.com/api/', - 'icon' => 'icon-urbanairship', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'web_push' => [ - 'name' => 'WebPush', - 'developers' => 'https://developer.mozilla.org/en-US/docs/Web/API/Push_API', - 'icon' => 'icon-webpush', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - ] ]; diff --git a/app/config/platforms.php b/app/config/platforms.php index 56103fad4a..76dcbca50d 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -24,7 +24,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'javascript', - 'source' => \realpath(__DIR__ . '/../sdks/client-web'), + 'source' => \realpath(__DIR__.'/../sdks/client-web'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-web.git', 'gitRepoName' => 'sdk-for-web', 'gitUserName' => 'appwrite', @@ -58,7 +58,7 @@ return [ 'source' => 'https://github.com/appwrite/todo-with-svelte', 'url' => 'https://appwrite-todo-with-svelte.vercel.app/', ], - ] + ], ], [ 'key' => 'flutter', @@ -72,7 +72,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'dart', - 'source' => \realpath(__DIR__ . '/../sdks/client-flutter'), + 'source' => \realpath(__DIR__.'/../sdks/client-flutter'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-flutter.git', 'gitRepoName' => 'sdk-for-flutter', 'gitUserName' => 'appwrite', @@ -90,7 +90,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'swift', - 'source' => \realpath(__DIR__ . '/../sdks/client-apple'), + 'source' => \realpath(__DIR__.'/../sdks/client-apple'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-apple.git', 'gitRepoName' => 'sdk-for-apple', 'gitUserName' => 'appwrite', @@ -125,7 +125,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'kotlin', - 'source' => \realpath(__DIR__ . '/../sdks/client-android'), + 'source' => \realpath(__DIR__.'/../sdks/client-android'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-android.git', 'gitRepoName' => 'sdk-for-android', 'gitUserName' => 'appwrite', @@ -147,7 +147,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'graphql', - 'source' => \realpath(__DIR__ . '/../sdks/client-graphql'), + 'source' => \realpath(__DIR__.'/../sdks/client-graphql'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', @@ -166,7 +166,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'http', - 'source' => \realpath(__DIR__ . '/../sdks/client-rest'), + 'source' => \realpath(__DIR__.'/../sdks/client-rest'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', @@ -194,7 +194,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_CONSOLE, 'prism' => 'javascript', - 'source' => \realpath(__DIR__ . '/../sdks/console-web'), + 'source' => \realpath(__DIR__.'/../sdks/console-web'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-console.git', 'gitBranch' => 'dev', 'gitRepoName' => 'sdk-for-console', @@ -212,7 +212,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CONSOLE, 'prism' => 'bash', - 'source' => \realpath(__DIR__ . '/../sdks/console-cli'), + 'source' => \realpath(__DIR__.'/../sdks/console-cli'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-cli.git', 'gitRepoName' => 'sdk-for-cli', 'gitUserName' => 'appwrite', @@ -240,7 +240,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'javascript', - 'source' => \realpath(__DIR__ . '/../sdks/server-nodejs'), + 'source' => \realpath(__DIR__.'/../sdks/server-nodejs'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-node.git', 'gitRepoName' => 'sdk-for-node', 'gitUserName' => 'appwrite', @@ -258,7 +258,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'typescript', - 'source' => \realpath(__DIR__ . '/../sdks/server-deno'), + 'source' => \realpath(__DIR__.'/../sdks/server-deno'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-deno.git', 'gitRepoName' => 'sdk-for-deno', 'gitUserName' => 'appwrite', @@ -276,7 +276,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'php', - 'source' => \realpath(__DIR__ . '/../sdks/server-php'), + 'source' => \realpath(__DIR__.'/../sdks/server-php'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-php.git', 'gitRepoName' => 'sdk-for-php', 'gitUserName' => 'appwrite', @@ -294,7 +294,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'python', - 'source' => \realpath(__DIR__ . '/../sdks/server-python'), + 'source' => \realpath(__DIR__.'/../sdks/server-python'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-python.git', 'gitRepoName' => 'sdk-for-python', 'gitUserName' => 'appwrite', @@ -312,7 +312,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'ruby', - 'source' => \realpath(__DIR__ . '/../sdks/server-ruby'), + 'source' => \realpath(__DIR__.'/../sdks/server-ruby'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-ruby.git', 'gitRepoName' => 'sdk-for-ruby', 'gitUserName' => 'appwrite', @@ -330,7 +330,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'go', - 'source' => \realpath(__DIR__ . '/../sdks/server-go'), + 'source' => \realpath(__DIR__.'/../sdks/server-go'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-go.git', 'gitRepoName' => 'sdk-for-go', 'gitUserName' => 'appwrite', @@ -348,7 +348,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'java', - 'source' => \realpath(__DIR__ . '/../sdks/server-java'), + 'source' => \realpath(__DIR__.'/../sdks/server-java'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-java.git', 'gitRepoName' => 'sdk-for-java', 'gitUserName' => 'appwrite', @@ -366,7 +366,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'csharp', - 'source' => \realpath(__DIR__ . '/../sdks/server-dotnet'), + 'source' => \realpath(__DIR__.'/../sdks/server-dotnet'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-dotnet.git', 'gitRepoName' => 'sdk-for-dotnet', 'gitUserName' => 'appwrite', @@ -384,7 +384,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'dart', - 'source' => \realpath(__DIR__ . '/../sdks/server-dart'), + 'source' => \realpath(__DIR__.'/../sdks/server-dart'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-dart.git', 'gitRepoName' => 'sdk-for-dart', 'gitUserName' => 'appwrite', @@ -402,7 +402,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'kotlin', - 'source' => \realpath(__DIR__ . '/../sdks/server-kotlin'), + 'source' => \realpath(__DIR__.'/../sdks/server-kotlin'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-kotlin.git', 'gitRepoName' => 'sdk-for-kotlin', 'gitUserName' => 'appwrite', @@ -424,7 +424,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'swift', - 'source' => \realpath(__DIR__ . '/../sdks/server-swift'), + 'source' => \realpath(__DIR__.'/../sdks/server-swift'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-swift.git', 'gitRepoName' => 'sdk-for-swift', 'gitUserName' => 'appwrite', @@ -442,7 +442,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_SERVER, 'prism' => 'graphql', - 'source' => \realpath(__DIR__ . '/../sdks/server-graphql'), + 'source' => \realpath(__DIR__.'/../sdks/server-graphql'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', @@ -461,7 +461,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_SERVER, 'prism' => 'http', - 'source' => \realpath(__DIR__ . '/../sdks/server-rest'), + 'source' => \realpath(__DIR__.'/../sdks/server-rest'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', diff --git a/app/config/regions.php b/app/config/regions.php index 0dc5fab1ed..cc920bee82 100644 --- a/app/config/regions.php +++ b/app/config/regions.php @@ -5,5 +5,5 @@ return [ 'name' => 'Default', 'default' => true, 'disabled' => false, - ] + ], ]; diff --git a/app/config/roles.php b/app/config/roles.php index 4bc85f7a28..cf1827e25e 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -25,7 +25,7 @@ $member = [ 'providers.write', 'providers.read', 'messages.write', - 'messages.read' + 'messages.read', ]; $admins = [ @@ -64,7 +64,7 @@ $admins = [ 'providers.write', 'providers.read', 'messages.write', - 'messages.read' + 'messages.read', ]; return [ diff --git a/app/config/runtimes.php b/app/config/runtimes.php index c24aaa109e..d249946d05 100644 --- a/app/config/runtimes.php +++ b/app/config/runtimes.php @@ -4,8 +4,8 @@ * List of Appwrite Cloud Functions supported runtimes */ -use Utopia\App; use Appwrite\Runtimes\Runtimes; +use Utopia\App; $runtimes = new Runtimes('v2'); diff --git a/app/config/scopes.php b/app/config/scopes.php index cf00654b1e..6dbc19d4aa 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -37,7 +37,7 @@ return [ // List of publicly visible scopes 'indexes.write' => [ 'description' => 'Access to create, update, and delete your project\'s database collection\'s indexes', ], - 'documents.read' => [ + 'documents.read' => [ 'description' => 'Access to read your project\'s database documents', ], 'documents.write' => [ @@ -111,5 +111,5 @@ return [ // List of publicly visible scopes ], 'targets.write' => [ 'description' => 'Access to create, update, and delete your project\'s targets', - ] + ], ]; diff --git a/app/config/services.php b/app/config/services.php index f80431f784..ee879eff94 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -66,8 +66,8 @@ return [ 'optional' => true, 'icon' => '/images/services/databases.png', 'globalAttributes' => [ - 'databaseId' - ] + 'databaseId', + ], ], 'locale' => [ 'key' => 'locale', @@ -237,5 +237,5 @@ return [ 'tests' => false, 'optional' => true, 'icon' => '/images/services/messaging.png', - ] + ], ]; diff --git a/app/config/usage.php b/app/config/usage.php index 2179bcce54..a0d3f9f725 100644 --- a/app/config/usage.php +++ b/app/config/usage.php @@ -1,24 +1,24 @@ [ - 'period' => '1h', - 'limit' => 24, - 'factor' => 3600, - ], - '7d' => [ - 'period' => '1d', - 'limit' => 7, - 'factor' => 86400, - ], - '30d' => [ - 'period' => '1d', - 'limit' => 30, - 'factor' => 86400, - ], - '90d' => [ - 'period' => '1d', - 'limit' => 90, - 'factor' => 86400, - ], + '24h' => [ + 'period' => '1h', + 'limit' => 24, + 'factor' => 3600, + ], + '7d' => [ + 'period' => '1d', + 'limit' => 7, + 'factor' => 86400, + ], + '30d' => [ + 'period' => '1d', + 'limit' => 30, + 'factor' => 86400, + ], + '90d' => [ + 'period' => '1d', + 'limit' => 90, + 'factor' => 86400, + ], ]; diff --git a/app/config/variables.php b/app/config/variables.php index c04ba339e5..136ecec5de 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -14,7 +14,7 @@ return [ 'default' => 'production', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_LOCALE', @@ -23,7 +23,7 @@ return [ 'default' => 'en', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_OPTIONS_ABUSE', @@ -32,7 +32,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_OPTIONS_FORCE_HTTPS', @@ -41,7 +41,7 @@ return [ 'default' => 'disabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_OPENSSL_KEY_V1', @@ -50,7 +50,7 @@ return [ 'default' => 'your-secret-key', 'required' => true, 'question' => 'Choose a secret API key, make sure to make a backup of your key in a secure location', - 'filter' => 'token' + 'filter' => 'token', ], [ 'name' => '_APP_DOMAIN', @@ -59,7 +59,7 @@ return [ 'default' => 'localhost', 'required' => true, 'question' => 'Enter your Appwrite hostname', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DOMAIN_TARGET', @@ -67,8 +67,8 @@ return [ 'introduction' => '', 'default' => 'localhost', 'required' => true, - 'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.' . PHP_EOL . 'You can use the same value as used for the Appwrite hostname.', - 'filter' => 'domainTarget' + 'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.'.PHP_EOL.'You can use the same value as used for the Appwrite hostname.', + 'filter' => 'domainTarget', ], [ 'name' => '_APP_CONSOLE_WHITELIST_ROOT', @@ -77,7 +77,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_CONSOLE_WHITELIST_EMAILS', @@ -86,7 +86,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], // [ // 'name' => '_APP_CONSOLE_WHITELIST_DOMAINS', @@ -103,7 +103,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_CONSOLE_ROOT_SESSION', @@ -112,7 +112,7 @@ return [ 'default' => 'disabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SYSTEM_EMAIL_NAME', @@ -121,7 +121,7 @@ return [ 'default' => 'Appwrite', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SYSTEM_EMAIL_ADDRESS', @@ -130,7 +130,7 @@ return [ 'default' => 'team@appwrite.io', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SYSTEM_RESPONSE_FORMAT', @@ -139,7 +139,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', @@ -148,7 +148,7 @@ return [ 'default' => 'certs@appwrite.io', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_USAGE_STATS', @@ -157,7 +157,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_LOGGING_PROVIDER', @@ -166,7 +166,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_LOGGING_CONFIG', @@ -175,7 +175,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_USAGE_AGGREGATION_INTERVAL', @@ -184,7 +184,7 @@ return [ 'default' => '30', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_USAGE_TIMESERIES_INTERVAL', @@ -193,7 +193,7 @@ return [ 'default' => '30', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_USAGE_DATABASE_INTERVAL', @@ -202,7 +202,7 @@ return [ 'default' => '900', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_WORKER_PER_CORE', @@ -211,7 +211,7 @@ return [ 'default' => 6, 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_CONSOLE_INVITES', @@ -220,7 +220,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], ], ], @@ -235,7 +235,7 @@ return [ 'default' => 'redis', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_REDIS_PORT', @@ -244,7 +244,7 @@ return [ 'default' => '6379', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_REDIS_USER', @@ -253,7 +253,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_REDIS_PASS', @@ -262,7 +262,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], ], ], @@ -277,7 +277,7 @@ return [ 'default' => 'mariadb', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DB_PORT', @@ -286,7 +286,7 @@ return [ 'default' => '3306', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DB_SCHEMA', @@ -295,7 +295,7 @@ return [ 'default' => 'appwrite', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DB_USER', @@ -304,7 +304,7 @@ return [ 'default' => 'user', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DB_PASS', @@ -313,7 +313,7 @@ return [ 'default' => 'password', 'required' => false, 'question' => '', - 'filter' => 'password' + 'filter' => 'password', ], [ 'name' => '_APP_DB_ROOT_PASS', @@ -322,7 +322,7 @@ return [ 'default' => 'rootsecretpassword', 'required' => false, 'question' => '', - 'filter' => 'password' + 'filter' => 'password', ], [ 'name' => '_APP_CONNECTIONS_MAX', @@ -331,26 +331,26 @@ return [ 'default' => 251, 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], -// [ -// 'name' => '_APP_CONNECTIONS_DB_PROJECT', -// 'description' => 'A list of comma-separated key value pairs representing Project DBs where key is the database name and value is the DSN connection string.', -// 'introduction' => 'TBD', -// 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', -// 'required' => true, -// 'question' => '', -// 'filter' => '' -// ], -// [ -// 'name' => '_APP_CONNECTIONS_DB_CONSOLE', -// 'description' => 'A key value pair representing the Console DB where key is the database name and value is the DSN connection string.', -// 'introduction' => 'TBD', -// 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', -// 'required' => true, -// 'question' => '', -// 'filter' => '' -// ] + // [ + // 'name' => '_APP_CONNECTIONS_DB_PROJECT', + // 'description' => 'A list of comma-separated key value pairs representing Project DBs where key is the database name and value is the DSN connection string.', + // 'introduction' => 'TBD', + // 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', + // 'required' => true, + // 'question' => '', + // 'filter' => '' + // ], + // [ + // 'name' => '_APP_CONNECTIONS_DB_CONSOLE', + // 'description' => 'A key value pair representing the Console DB where key is the database name and value is the DSN connection string.', + // 'introduction' => 'TBD', + // 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', + // 'required' => true, + // 'question' => '', + // 'filter' => '' + // ] ], ], [ @@ -364,7 +364,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SMTP_PORT', @@ -373,7 +373,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SMTP_SECURE', @@ -382,7 +382,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SMTP_USERNAME', @@ -391,7 +391,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SMTP_PASSWORD', @@ -400,7 +400,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], ], ], @@ -415,7 +415,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_SMS_FROM', @@ -424,7 +424,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], ], ], @@ -439,7 +439,7 @@ return [ 'default' => '30000000', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_STORAGE_PREVIEW_LIMIT', @@ -448,7 +448,7 @@ return [ 'default' => '20000000', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_STORAGE_ANTIVIRUS', @@ -457,7 +457,7 @@ return [ 'default' => 'disabled', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_STORAGE_ANTIVIRUS_HOST', @@ -466,7 +466,7 @@ return [ 'default' => 'clamav', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_STORAGE_ANTIVIRUS_PORT', @@ -475,7 +475,7 @@ return [ 'default' => '3310', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_CONNECTIONS_STORAGE', @@ -666,7 +666,7 @@ return [ 'default' => '30000000', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_TIMEOUT', @@ -675,7 +675,7 @@ return [ 'default' => '900', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT', @@ -684,7 +684,7 @@ return [ 'default' => '900', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_CONTAINERS', @@ -693,7 +693,7 @@ return [ 'default' => '10', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_CPUS', @@ -702,7 +702,7 @@ return [ 'default' => '0', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_MEMORY', @@ -711,7 +711,7 @@ return [ 'default' => '0', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_MEMORY_SWAP', @@ -720,16 +720,16 @@ return [ 'default' => '0', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_RUNTIMES', - 'description' => "This option allows you to enable or disable runtime environments for cloud functions. Disable unused runtimes to save disk space.\n\nTo enable cloud function runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))), + 'description' => "This option allows you to enable or disable runtime environments for cloud functions. Disable unused runtimes to save disk space.\n\nTo enable cloud function runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: ".\implode(', ', \array_keys(Config::getParam('runtimes'))), 'introduction' => '0.8.0', 'default' => 'node-16.0,php-8.0,python-3.9,ruby-3.0', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_EXECUTOR_SECRET', @@ -738,7 +738,7 @@ return [ 'default' => 'your-secret-key', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_EXECUTOR_HOST', @@ -747,7 +747,7 @@ return [ 'default' => 'http://appwrite-executor/v1', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_EXECUTOR_RUNTIME_NETWORK', @@ -756,7 +756,7 @@ return [ 'default' => 'appwrite_runtimes', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_ENVS', @@ -765,7 +765,7 @@ return [ 'default' => 'node-16.0,php-7.4,python-3.9,ruby-3.0', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_INACTIVE_THRESHOLD', @@ -774,7 +774,7 @@ return [ 'default' => '60', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => 'DOCKERHUB_PULL_USERNAME', @@ -783,7 +783,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => 'DOCKERHUB_PULL_PASSWORD', @@ -792,7 +792,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => 'DOCKERHUB_PULL_EMAIL', @@ -801,7 +801,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => 'OPEN_RUNTIMES_NETWORK', @@ -810,7 +810,7 @@ return [ 'default' => 'appwrite_runtimes', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_RUNTIMES_NETWORK', @@ -819,7 +819,7 @@ return [ 'default' => 'runtimes', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DOCKER_HUB_USERNAME', @@ -828,7 +828,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_DOCKER_HUB_PASSWORD', @@ -837,7 +837,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_FUNCTIONS_MAINTENANCE_INTERVAL', @@ -846,7 +846,7 @@ return [ 'default' => '60', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], ], ], @@ -861,7 +861,7 @@ return [ 'default' => '86400', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_MAINTENANCE_RETENTION_CACHE', @@ -870,7 +870,7 @@ return [ 'default' => '2592000', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_MAINTENANCE_RETENTION_EXECUTION', @@ -879,7 +879,7 @@ return [ 'default' => '1209600', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_MAINTENANCE_RETENTION_AUDIT', @@ -888,7 +888,7 @@ return [ 'default' => '1209600', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_MAINTENANCE_RETENTION_ABUSE', @@ -897,7 +897,7 @@ return [ 'default' => '86400', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_MAINTENANCE_RETENTION_USAGE_HOURLY', @@ -906,7 +906,7 @@ return [ 'default' => '8640000', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_MAINTENANCE_RETENTION_SCHEDULES', @@ -915,8 +915,8 @@ return [ 'default' => '86400', 'required' => false, 'question' => '', - 'filter' => '' - ] + 'filter' => '', + ], ], ], [ @@ -930,7 +930,7 @@ return [ 'default' => '10', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_GRAPHQL_MAX_COMPLEXITY', @@ -939,7 +939,7 @@ return [ 'default' => '250', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], [ 'name' => '_APP_GRAPHQL_MAX_DEPTH', @@ -948,7 +948,7 @@ return [ 'default' => '3', 'required' => false, 'question' => '', - 'filter' => '' + 'filter' => '', ], ], ], diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 46acd2efdb..8f9fc34635 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4,6 +4,9 @@ use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; use Appwrite\Auth\OAuth2\Exception as OAuth2Exception; use Appwrite\Auth\Validator\Password; +use Appwrite\Auth\Validator\PasswordDictionary; +use Appwrite\Auth\Validator\PasswordHistory; +use Appwrite\Auth\Validator\PersonalData; use Appwrite\Auth\Validator\Phone; use Appwrite\Detector\Detector; use Appwrite\Event\Event; @@ -11,16 +14,11 @@ use Appwrite\Event\Mail; use Appwrite\Event\Phone as EventPhone; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; -use Utopia\Validator\Host; -use Utopia\Validator\URL; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Template\Template; use Appwrite\URL\URL as URLParser; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; -use Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -28,23 +26,25 @@ use Utopia\App; use Utopia\Audit\Audit as EventAudit; use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Query; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; +use Utopia\Validator\Host; use Utopia\Validator\Text; +use Utopia\Validator\URL; use Utopia\Validator\WhiteList; -use Appwrite\Auth\Validator\PasswordHistory; -use Appwrite\Auth\Validator\PasswordDictionary; -use Appwrite\Auth\Validator\PersonalData; $oauthDefaultSuccess = '/auth/oauth2/success'; $oauthDefaultFailure = '/auth/oauth2/failure'; @@ -77,20 +77,19 @@ App::post('/v1/account/invite') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $email, string $password, string $name, string $code, Request $request, Response $response, Document $project, Database $dbForProject, Event $events) { - if ($project->getId() !== 'console') { throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN); } $email = \strtolower($email); - $whitelistCodes = (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null)) : []; + $whitelistCodes = (! empty(App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null)) : []; if (empty($whitelistCodes)) { throw new Exception(Exception::GENERAL_CODES_DISABLED); } - if (!empty($whitelistCodes) && !\in_array($code, $whitelistCodes)) { + if (! empty($whitelistCodes) && ! \in_array($code, $whitelistCodes)) { throw new Exception(Exception::USER_INVALID_CODE); } @@ -106,7 +105,7 @@ App::post('/v1/account/invite') try { $userId = $userId == 'unique()' ? ID::unique() : $userId; - $user = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([ + $user = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ Permission::read(Role::any()), @@ -127,7 +126,7 @@ App::post('/v1/account/invite') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]) + 'search' => implode(' ', [$userId, $email, $name]), ]))); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); @@ -177,11 +176,11 @@ App::post('/v1/account') $whitelistEmails = $project->getAttribute('authWhitelistEmails'); $whitelistIPs = $project->getAttribute('authWhitelistIPs'); - if (!empty($whitelistEmails) && !\in_array($email, $whitelistEmails) && !\in_array(strtoupper($email), $whitelistEmails)) { + if (! empty($whitelistEmails) && ! \in_array($email, $whitelistEmails) && ! \in_array(strtoupper($email), $whitelistEmails)) { throw new Exception(Exception::USER_EMAIL_NOT_WHITELISTED); } - if (!empty($whitelistIPs) && !\in_array($request->getIP(), $whitelistIPs)) { + if (! empty($whitelistIPs) && ! \in_array($request->getIP(), $whitelistIPs)) { throw new Exception(Exception::USER_IP_NOT_WHITELISTED); } } @@ -200,13 +199,13 @@ App::post('/v1/account') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($userId, $email, $name, null); - if (!$personalDataValidator->isValid($password)) { + if (! $personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } @@ -240,7 +239,7 @@ App::post('/v1/account') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), // Add this here to make sure it's returned in the response ]); - Authorization::skip(fn() => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } @@ -286,7 +285,6 @@ App::post('/v1/account/sessions/email') ->inject('geodb') ->inject('events') ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $events) { - $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -294,7 +292,7 @@ App::post('/v1/account/sessions/email') Query::equal('email', [$email]), ]); - if (!$profile || empty($profile->getAttribute('passwordUpdate')) || !Auth::passwordVerify($password, $profile->getAttribute('password'), $profile->getAttribute('hash'), $profile->getAttribute('hashOptions'))) { + if (! $profile || empty($profile->getAttribute('passwordUpdate')) || ! Auth::passwordVerify($password, $profile->getAttribute('password'), $profile->getAttribute('hash'), $profile->getAttribute('hashOptions'))) { throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -346,31 +344,26 @@ App::post('/v1/account/sessions/email') Permission::delete(Role::user($user->getId())), ])); - - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response - ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) - ; + ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $response - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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) - ; + ->setStatusCode(Response::STATUS_CODE_CREATED); - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire) - ; + ->setAttribute('expire', $expire); $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()) - ; + ->setParam('sessionId', $session->getId()); $response->dynamic($session, Response::MODEL_SESSION); }); @@ -378,7 +371,7 @@ App::post('/v1/account/sessions/email') App::get('/v1/account/sessions/oauth2/:provider') ->desc('Create OAuth2 Session') ->groups(['api', 'account']) - ->label('error', __DIR__ . '/../../views/general/error.phtml') + ->label('error', __DIR__.'/../../views/general/error.phtml') ->label('scope', 'public') ->label('sdk.auth', []) ->label('sdk.namespace', 'account') @@ -389,48 +382,47 @@ App::get('/v1/account/sessions/oauth2/:provider') ->label('sdk.methodType', 'webAuth') ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') - ->param('provider', '', new WhiteList(\array_keys(Config::getParam('authProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('authProviders'), fn($node) => (!$node['mock'])))) . '.') - ->param('success', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. 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.', true, ['clients']) - ->param('failure', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. 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.', true, ['clients']) - ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->param('provider', '', new WhiteList(\array_keys(Config::getParam('authProviders')), true), 'OAuth2 Provider. Currently, supported providers are: '.\implode(', ', \array_keys(\array_filter(Config::getParam('authProviders'), fn ($node) => (! $node['mock'])))).'.') + ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. 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.', true, ['clients']) + ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. 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.', true, ['clients']) + ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' scopes are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long.', true) ->inject('request') ->inject('response') ->inject('project') ->action(function (string $provider, string $success, string $failure, array $scopes, Request $request, Response $response, Document $project) use ($oauthDefaultSuccess, $oauthDefaultFailure) { - $protocol = $request->getProtocol(); - $callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId(); - $providerEnabled = $project->getAttribute('authProviders', [])[$provider . 'Enabled'] ?? false; + $callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId(); + $providerEnabled = $project->getAttribute('authProviders', [])[$provider.'Enabled'] ?? false; - if (!$providerEnabled) { - throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your ' . APP_NAME . ' console to continue.'); + if (! $providerEnabled) { + throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your '.APP_NAME.' console to continue.'); } - $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; - if (!empty($appSecret) && isset($appSecret['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']); + if (! empty($appSecret) && isset($appSecret['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$appSecret['version']); $appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, \hex2bin($appSecret['iv']), \hex2bin($appSecret['tag'])); } if (empty($appId) || empty($appSecret)) { - throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.'); + throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please configure the provider app ID and app secret key from your '.APP_NAME.' console to continue.'); } - $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); - if (!\class_exists($className)) { + if (! \class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } if (empty($success)) { - $success = $protocol . '://' . $request->getHostname() . $oauthDefaultSuccess; + $success = $protocol.'://'.$request->getHostname().$oauthDefaultSuccess; } if (empty($failure)) { - $failure = $protocol . '://' . $request->getHostname() . $oauthDefaultFailure; + $failure = $protocol.'://'.$request->getHostname().$oauthDefaultFailure; } $oauth2 = new $className($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure], $scopes); @@ -444,7 +436,7 @@ App::get('/v1/account/sessions/oauth2/:provider') App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->desc('OAuth2 Callback') ->groups(['account']) - ->label('error', __DIR__ . '/../../views/general/error.phtml') + ->label('error', __DIR__.'/../../views/general/error.phtml') ->label('scope', 'public') ->label('docs', false) ->param('projectId', '', new Text(1024), 'Project ID.') @@ -456,27 +448,26 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->inject('request') ->inject('response') ->action(function (string $projectId, string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response) { - $domain = $request->getHostname(); $protocol = $request->getProtocol(); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') - ->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?' - . \http_build_query([ + ->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?' + .\http_build_query([ 'project' => $projectId, 'code' => $code, 'state' => $state, 'error' => $error, - 'error_description' => $error_description + 'error_description' => $error_description, ])); }); App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->desc('OAuth2 Callback') ->groups(['account']) - ->label('error', __DIR__ . '/../../views/general/error.phtml') + ->label('error', __DIR__.'/../../views/general/error.phtml') ->label('scope', 'public') ->label('origin', '*') ->label('docs', false) @@ -489,27 +480,26 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->inject('request') ->inject('response') ->action(function (string $projectId, string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response) { - $domain = $request->getHostname(); $protocol = $request->getProtocol(); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') - ->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?' - . \http_build_query([ + ->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?' + .\http_build_query([ 'project' => $projectId, 'code' => $code, 'state' => $state, 'error' => $error, - 'error_description' => $error_description + 'error_description' => $error_description, ])); }); App::get('/v1/account/sessions/oauth2/:provider/redirect') ->desc('OAuth2 Redirect') ->groups(['api', 'account', 'session']) - ->label('error', __DIR__ . '/../../views/general/error.phtml') + ->label('error', __DIR__.'/../../views/general/error.phtml') ->label('event', 'users.[userId].sessions.[sessionId].create') ->label('scope', 'public') ->label('audits.event', 'session.create') @@ -531,18 +521,17 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('geodb') ->inject('events') ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $events) use ($oauthDefaultSuccess) { - $protocol = $request->getProtocol(); - $callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId(); + $callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId(); $defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => '']; $validateURL = new URL(); - $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; - $providerEnabled = $project->getAttribute('authProviders', [])[$provider . 'Enabled'] ?? false; + $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $providerEnabled = $project->getAttribute('authProviders', [])[$provider.'Enabled'] ?? false; - $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); - if (!\class_exists($className)) { + if (! \class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } @@ -552,7 +541,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') /** @var Appwrite\Auth\OAuth2 $oauth2 */ $oauth2 = new $className($appId, $appSecret, $callback); - if (!empty($state)) { + if (! empty($state)) { try { $state = \array_merge($defaultState, $oauth2->parseState($state)); } catch (\Exception $exception) { @@ -562,25 +551,25 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $state = $defaultState; } - if (!$validateURL->isValid($state['success'])) { + if (! $validateURL->isValid($state['success'])) { throw new Exception(Exception::PROJECT_INVALID_SUCCESS_URL); } - if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) { + if (! empty($state['failure']) && ! $validateURL->isValid($state['failure'])) { throw new Exception(Exception::PROJECT_INVALID_FAILURE_URL); } $failure = []; - if (!empty($state['failure'])) { + if (! empty($state['failure'])) { $failure = URLParser::parse($state['failure']); } $failureRedirect = (function (string $type, ?string $message = null, ?int $code = null) use ($failure, $response) { $exception = new Exception($type, $message, $code); - if (!empty($failure)) { + if (! empty($failure)) { $query = URLParser::parseQuery($failure['query']); $query['error'] = json_encode([ 'message' => $exception->getMessage(), 'type' => $exception->getType(), - 'code' => !\is_null($code) ? $code : $exception->getCode(), + 'code' => ! \is_null($code) ? $code : $exception->getCode(), ]); $failure['query'] = URLParser::unparseQuery($query); $response->redirect(URLParser::unparse($failure), 301); @@ -589,14 +578,14 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') throw $exception; }); - if (!$providerEnabled) { - $failureRedirect(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your ' . APP_NAME . ' console to continue.'); + if (! $providerEnabled) { + $failureRedirect(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your '.APP_NAME.' console to continue.'); } - if (!empty($error)) { - $message = 'The ' . $providerName . ' OAuth2 provider returned an error: ' . $error; - if (!empty($error_description)) { - $message .= ': ' . $error_description; + if (! empty($error)) { + $message = 'The '.$providerName.' OAuth2 provider returned an error: '.$error; + if (! empty($error_description)) { + $message .= ': '.$error_description; } $failureRedirect(Exception::USER_OAUTH2_PROVIDER_ERROR, $message); } @@ -605,8 +594,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $failureRedirect(Exception::USER_OAUTH2_PROVIDER_ERROR, 'Missing OAuth2 code. Please contact the Appwrite team for additional support.'); } - if (!empty($appSecret) && isset($appSecret['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']); + if (! empty($appSecret) && isset($appSecret['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$appSecret['version']); $appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, \hex2bin($appSecret['iv']), \hex2bin($appSecret['tag'])); } @@ -621,7 +610,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } catch (OAuth2Exception $ex) { $failureRedirect( $ex->getType(), - 'Failed to obtain access token. The ' . $providerName . ' OAuth2 provider returned an error: ' . $ex->getMessage(), + 'Failed to obtain access token. The '.$providerName.' OAuth2 provider returned an error: '.$ex->getMessage(), $ex->getCode(), ); } @@ -635,14 +624,14 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $email = $oauth2->getUserEmail($accessToken); // Check if this identity is connected to a different user - if (!$user->isEmpty()) { + if (! $user->isEmpty()) { $userId = $user->getId(); $identitiesWithMatchingEmail = $dbForProject->find('identities', [ Query::equal('providerEmail', [$email]), Query::notEqual('userId', $userId), ]); - if (!empty($identitiesWithMatchingEmail)) { + if (! empty($identitiesWithMatchingEmail)) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } @@ -653,7 +642,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') if ($current) { // Delete current session of new one. $currentDocument = $dbForProject->getDocument('sessions', $current); - if (!$currentDocument->isEmpty()) { + if (! $currentDocument->isEmpty()) { $dbForProject->deleteDocument('sessions', $currentDocument->getId()); $dbForProject->deleteCachedDocument('users', $user->getId()); } @@ -664,7 +653,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('provider', [$provider]), Query::equal('providerUid', [$oauth2ID]), ]); - if ($session !== false && !$session->isEmpty()) { + if ($session !== false && ! $session->isEmpty()) { $user->setAttributes($dbForProject->getDocument('users', $session->getAttribute('userId'))->getArrayCopy()); } } @@ -682,7 +671,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $userWithEmail = $dbForProject->findOne('users', [ Query::equal('email', [$email]), ]); - if ($userWithEmail !== false && !$userWithEmail->isEmpty()) { + if ($userWithEmail !== false && ! $userWithEmail->isEmpty()) { $user->setAttributes($userWithEmail->getArrayCopy()); } @@ -693,7 +682,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('providerUid', [$oauth2ID]), ]); - if ($identity !== false && !$identity->isEmpty()) { + if ($identity !== false && ! $identity->isEmpty()) { $user = $dbForProject->getDocument('users', $identity->getAttribute('userId')); } } @@ -713,7 +702,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } @@ -740,9 +729,9 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]) + 'search' => implode(' ', [$userId, $email, $name]), ]); - Authorization::skip(fn() => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } catch (Duplicate $th) { $failureRedirect(Exception::USER_ALREADY_EXISTS); } @@ -769,7 +758,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('providerEmail', [$email]), Query::notEqual('userId', $user->getId()), ]); - if (!empty($identitiesWithMatchingEmail)) { + if (! empty($identitiesWithMatchingEmail)) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } @@ -787,13 +776,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); } @@ -812,7 +801,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'providerUid' => $oauth2ID, 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), + 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry), 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -828,8 +817,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } $user - ->setAttribute('status', true) - ; + ->setAttribute('status', true); Authorization::setRole(Role::user($user->getId())->toString()); @@ -848,10 +836,9 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $events ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()) - ->setPayload($response->output($session, Response::MODEL_SESSION)) - ; + ->setPayload($response->output($session, Response::MODEL_SESSION)); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } @@ -870,10 +857,9 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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')) - ->redirect($state['success']) - ; + ->redirect($state['success']); }); App::get('/v1/account/identities') @@ -889,12 +875,11 @@ App::get('/v1/account/identities') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) ->label('sdk.offline.model', '/account/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('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) ->inject('response') ->inject('user') ->inject('dbForProject') ->action(function (array $queries, Response $response, Document $user, Database $dbForProject) { - $queries = Query::parseQueries($queries); $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); @@ -944,7 +929,6 @@ App::delete('/v1/account/identities/:identityId') ->inject('response') ->inject('dbForProject') ->action(function (string $identityId, Response $response, Database $dbForProject) { - $identity = $dbForProject->getDocument('identities', $identityId); if ($identity->isEmpty()) { @@ -975,7 +959,7 @@ App::post('/v1/account/sessions/magic-url') ->label('abuse-key', 'url:{url},email:{param-email}') ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') - ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. 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.', true, ['clients']) + ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. 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.', true, ['clients']) ->inject('request') ->inject('response') ->inject('user') @@ -985,7 +969,6 @@ App::post('/v1/account/sessions/magic-url') ->inject('events') ->inject('mails') ->action(function (string $userId, string $email, string $url, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $events, Mail $mails) { - if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -995,7 +978,7 @@ App::post('/v1/account/sessions/magic-url') $isAppUser = Auth::isAppUser($roles); $result = $dbForProject->findOne('users', [Query::equal('email', [$email])]); - if ($result !== false && !$result->isEmpty()) { + if ($result !== false && ! $result->isEmpty()) { $user->setAttributes($result->getArrayCopy()); } else { $limit = $project->getAttribute('auths', [])['limit'] ?? 0; @@ -1012,7 +995,7 @@ App::post('/v1/account/sessions/magic-url') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } @@ -1038,7 +1021,7 @@ App::post('/v1/account/sessions/magic-url') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email]) + 'search' => implode(' ', [$userId, $email]), ]); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); @@ -1070,7 +1053,7 @@ App::post('/v1/account/sessions/magic-url') $dbForProject->deleteCachedDocument('users', $user->getId()); if (empty($url)) { - $url = $request->getProtocol() . '://' . $request->getHostname() . '/auth/magic-url'; + $url = $request->getProtocol().'://'.$request->getHostname().'/auth/magic-url'; } $url = Template::parseURL($url); @@ -1078,12 +1061,12 @@ App::post('/v1/account/sessions/magic-url') $url = Template::unParseURL($url); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $project->getAttribute('name')); - $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); - $subject = $locale->getText("emails.magicSession.subject"); + $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); + $subject = $locale->getText('emails.magicSession.subject'); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.magicSession-' . $locale->default] ?? []; - if ($smtpEnabled && !empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.magicSession-'.$locale->default] ?? []; + if ($smtpEnabled && ! empty($customTemplate)) { $body = $customTemplate['message'] ?? $body; $subject = $customTemplate['subject'] ?? $subject; $from = $customTemplate['senderName'] ?? $from; @@ -1091,13 +1074,13 @@ App::post('/v1/account/sessions/magic-url') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText("emails.magicSession.hello")) + ->setParam('{{hello}}', $locale->getText('emails.magicSession.hello')) ->setParam('{{name}}', '') - ->setParam('{{body}}', $locale->getText("emails.magicSession.body")) + ->setParam('{{body}}', $locale->getText('emails.magicSession.body')) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText("emails.magicSession.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.magicSession.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.magicSession.signature")) + ->setParam('{{footer}}', $locale->getText('emails.magicSession.footer')) + ->setParam('{{thanks}}', $locale->getText('emails.magicSession.thanks')) + ->setParam('{{signature}}', $locale->getText('emails.magicSession.signature')) ->setParam('{{project}}', $project->getAttribute('name')) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -1111,8 +1094,7 @@ App::post('/v1/account/sessions/magic-url') ->setBody($body) ->setFrom($from) ->setRecipient($user->getAttribute('email')) - ->trigger() - ; + ->trigger(); $events->setPayload( $response->output( @@ -1126,8 +1108,7 @@ App::post('/v1/account/sessions/magic-url') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN) - ; + ->dynamic($token, Response::MODEL_TOKEN); }); App::put('/v1/account/sessions/magic-url') @@ -1158,10 +1139,8 @@ App::put('/v1/account/sessions/magic-url') ->inject('geodb') ->inject('events') ->action(function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $events) { - /** @var Utopia\Database\Document $user */ - - $userFromRequest = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); + $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1169,7 +1148,7 @@ App::put('/v1/account/sessions/magic-url') $token = Auth::tokenVerify($userFromRequest->getAttribute('tokens', []), Auth::TOKEN_TYPE_MAGIC_URL, $secret); - if (!$token) { + if (! $token) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -1227,28 +1206,25 @@ App::put('/v1/account/sessions/magic-url') $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()) - ; + ->setParam('sessionId', $session->getId()); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $protocol = $request->getProtocol(); $response - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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) - ; + ->setStatusCode(Response::STATUS_CODE_CREATED); - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire) - ; + ->setAttribute('expire', $expire); $response->dynamic($session, Response::MODEL_SESSION); }); @@ -1281,7 +1257,6 @@ App::post('/v1/account/sessions/phone') ->inject('messaging') ->inject('locale') ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, EventPhone $messaging, Locale $locale) { - if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -1291,7 +1266,7 @@ App::post('/v1/account/sessions/phone') $isAppUser = Auth::isAppUser($roles); $result = $dbForProject->findOne('users', [Query::equal('phone', [$phone])]); - if ($result !== false && !$result->isEmpty()) { + if ($result !== false && ! $result->isEmpty()) { $user->setAttributes($result->getArrayCopy()); } else { $limit = $project->getAttribute('auths', [])['limit'] ?? 0; @@ -1325,7 +1300,7 @@ App::post('/v1/account/sessions/phone') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $phone]) + 'search' => implode(' ', [$userId, $phone]), ]); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); @@ -1356,10 +1331,10 @@ App::post('/v1/account/sessions/phone') $dbForProject->deleteCachedDocument('users', $user->getId()); - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); + $message = Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.login-' . $locale->default] ?? []; - if (!empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['sms.login-'.$locale->default] ?? []; + if (! empty($customTemplate)) { $message = $customTemplate['message'] ?? $message; } @@ -1383,8 +1358,7 @@ App::post('/v1/account/sessions/phone') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN) - ; + ->dynamic($token, Response::MODEL_TOKEN); }); App::put('/v1/account/sessions/phone') @@ -1412,8 +1386,7 @@ App::put('/v1/account/sessions/phone') ->inject('geodb') ->inject('events') ->action(function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $events) { - - $userFromRequest = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); + $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1421,7 +1394,7 @@ App::put('/v1/account/sessions/phone') $token = Auth::phoneTokenVerify($userFromRequest->getAttribute('tokens', []), $secret); - if (!$token) { + if (! $token) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -1477,28 +1450,25 @@ App::put('/v1/account/sessions/phone') $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()) - ; + ->setParam('sessionId', $session->getId()); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $protocol = $request->getProtocol(); $response - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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) - ; + ->setStatusCode(Response::STATUS_CODE_CREATED); - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire) - ; + ->setAttribute('expire', $expire); $response->dynamic($session, Response::MODEL_SESSION); }); @@ -1530,14 +1500,13 @@ App::post('/v1/account/sessions/anonymous') ->inject('geodb') ->inject('events') ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $events) { - $protocol = $request->getProtocol(); if ('console' === $project->getId()) { throw new Exception(Exception::USER_ANONYMOUS_CONSOLE_PROHIBITED, 'Failed to create anonymous user'); } - if (!$user->isEmpty()) { + if (! $user->isEmpty()) { throw new Exception(Exception::USER_SESSION_ALREADY_EXISTS, 'Cannot create an anonymous user when logged in'); } @@ -1575,7 +1544,7 @@ App::post('/v1/account/sessions/anonymous') 'memberships' => null, 'search' => $userId, ]); - Authorization::skip(fn() => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; @@ -1602,36 +1571,33 @@ App::post('/v1/account/sessions/anonymous') Authorization::setRole(Role::user($user->getId())->toString()); - $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())), - ])); + $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())), + ])); $dbForProject->deleteCachedDocument('users', $user->getId()); $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()) - ; + ->setParam('sessionId', $session->getId()); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $response - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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) - ; + ->setStatusCode(Response::STATUS_CODE_CREATED); - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire) - ; + ->setAttribute('expire', $expire); $response->dynamic($session, Response::MODEL_SESSION); }); @@ -1654,8 +1620,6 @@ App::post('/v1/account/jwt') ->inject('user') ->inject('dbForProject') ->action(function (Response $response, Document $user, Database $dbForProject) { - - $sessions = $user->getAttribute('sessions', []); $current = new Document(); @@ -1674,13 +1638,13 @@ App::post('/v1/account/jwt') $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic(new Document(['jwt' => $jwt->encode([ - // 'uid' => 1, - // 'aud' => 'http://site.com', - // 'scopes' => ['user'], - // 'iss' => 'http://api.mysite.com', - 'userId' => $user->getId(), - 'sessionId' => $current->getId(), - ])]), Response::MODEL_JWT); + // 'uid' => 1, + // 'aud' => 'http://site.com', + // 'scopes' => ['user'], + // 'iss' => 'http://api.mysite.com', + 'userId' => $user->getId(), + 'sessionId' => $current->getId(), + ])]), Response::MODEL_JWT); }); App::get('/v1/account') @@ -1699,7 +1663,6 @@ App::get('/v1/account') ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { - $response->dynamic($user, Response::MODEL_ACCOUNT); }); @@ -1719,7 +1682,6 @@ App::get('/v1/account/prefs') ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { - $prefs = $user->getAttribute('prefs', []); $response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES); @@ -1742,13 +1704,12 @@ App::get('/v1/account/sessions') ->inject('locale') ->inject('project') ->action(function (Response $response, Document $user, Locale $locale, Document $project) { - $sessions = $user->getAttribute('sessions', []); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $current = Auth::sessionVerify($sessions, Auth::$secret, $authDuration); foreach ($sessions as $key => $session) {/** @var Document $session */ - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session->setAttribute('countryName', $countryName); $session->setAttribute('current', ($current == $session->getId()) ? true : false); @@ -1781,7 +1742,6 @@ App::get('/v1/account/logs') ->inject('geodb') ->inject('dbForProject') ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { - $queries = Query::parseQueries($queries); $grouped = Query::groupByType($queries); $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; @@ -1794,7 +1754,7 @@ App::get('/v1/account/logs') $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); @@ -1809,8 +1769,8 @@ App::get('/v1/account/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -1837,7 +1797,6 @@ App::get('/v1/account/targets') ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { - $targets = $user->getAttribute('targets', []); $response->dynamic(new Document([ @@ -1866,7 +1825,6 @@ App::get('/v1/account/sessions/:sessionId') ->inject('dbForProject') ->inject('project') ->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Database $dbForProject, Document $project) { - $sessions = $user->getAttribute('sessions', []); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $sessionId = ($sessionId === 'current') @@ -1875,13 +1833,12 @@ App::get('/v1/account/sessions/:sessionId') foreach ($sessions as $session) {/** @var Document $session */ if ($sessionId == $session->getId()) { - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret))) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', DateTime::formatTz(DateTime::addSeconds(new \DateTime($session->getCreatedAt()), $authDuration))) - ; + ->setAttribute('expire', DateTime::formatTz(DateTime::addSeconds(new \DateTime($session->getCreatedAt()), $authDuration))); return $response->dynamic($session, Response::MODEL_SESSION); } @@ -1907,7 +1864,6 @@ App::get('/v1/account/targets/:targetId') ->inject('response') ->inject('user') ->action(function (string $targetId, Response $response, Document $user) { - $target = $user->find('$id', $targetId, 'targets'); if (empty($target)) { @@ -1940,7 +1896,6 @@ App::patch('/v1/account/name') ->inject('dbForProject') ->inject('events') ->action(function (string $name, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $events) { - $user->setAttribute('name', $name); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); @@ -1976,9 +1931,8 @@ App::patch('/v1/account/password') ->inject('dbForProject') ->inject('events') ->action(function (string $password, string $oldPassword, ?\DateTime $requestTimestamp, Response $response, Document $user, Document $project, Database $dbForProject, Event $events) { - // Check old password only if its an existing user. - if (!empty($user->getAttribute('passwordUpdate')) && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions'))) { // 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); } @@ -1987,7 +1941,7 @@ App::patch('/v1/account/password') $history = $user->getAttribute('passwordHistory', []); if ($historyLimit > 0) { $validator = new PasswordHistory($history, $user->getAttribute('hash'), $user->getAttribute('hashOptions')); - if (!$validator->isValid($password)) { + if (! $validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -1997,7 +1951,7 @@ App::patch('/v1/account/password') if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($user->getId(), $user->getAttribute('email'), $user->getAttribute('name'), $user->getAttribute('phone')); - if (!$personalDataValidator->isValid($password)) { + if (! $personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } @@ -2044,8 +1998,8 @@ App::patch('/v1/account/email') $passwordUpdate = $user->getAttribute('passwordUpdate'); if ( - !empty($passwordUpdate) && - !Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) + ! empty($passwordUpdate) && + ! Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) ) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -2057,14 +2011,14 @@ App::patch('/v1/account/email') Query::equal('providerEmail', [$email]), Query::notEqual('userId', $user->getId()), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } $user ->setAttribute('email', $email) ->setAttribute('emailVerification', false) // After this user needs to confirm mail again - ; +; if (empty($passwordUpdate)) { $user @@ -2113,8 +2067,8 @@ App::patch('/v1/account/phone') $passwordUpdate = $user->getAttribute('passwordUpdate'); if ( - !empty($passwordUpdate) && - !Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) + ! empty($passwordUpdate) && + ! Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) ) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -2122,7 +2076,7 @@ App::patch('/v1/account/phone') $user ->setAttribute('phone', $phone) ->setAttribute('phoneVerification', false) // After this user needs to confirm phone number again - ; +; if (empty($passwordUpdate)) { $user @@ -2166,7 +2120,6 @@ App::patch('/v1/account/prefs') ->inject('dbForProject') ->inject('events') ->action(function (array $prefs, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $events) { - $user->setAttribute('prefs', $prefs); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); @@ -2197,7 +2150,6 @@ App::patch('/v1/account/status') ->inject('dbForProject') ->inject('events') ->action(function (?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Event $events) { - $user->setAttribute('status', false); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); @@ -2206,15 +2158,14 @@ App::patch('/v1/account/status') ->setParam('userId', $user->getId()) ->setPayload($response->output($user, Response::MODEL_ACCOUNT)); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([])); } $protocol = $request->getProtocol(); $response - ->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')) - ; + ->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); }); @@ -2243,7 +2194,6 @@ App::delete('/v1/account/sessions/:sessionId') ->inject('events') ->inject('project') ->action(function (?string $sessionId, ?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $events, Document $project) { - $protocol = $request->getProtocol(); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $sessionId = ($sessionId === 'current') @@ -2265,19 +2215,16 @@ App::delete('/v1/account/sessions/:sessionId') 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'))) - ; + ->setAttribute('countryName', $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response - ->addHeader('X-Fallback-Cookies', \json_encode([])) - ; + ->addHeader('X-Fallback-Cookies', \json_encode([])); } $response - ->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')) - ; + ->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->deleteCachedDocument('users', $user->getId()); @@ -2285,8 +2232,8 @@ App::delete('/v1/account/sessions/:sessionId') $events ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()) - ->setPayload($response->output($session, Response::MODEL_SESSION)) - ; + ->setPayload($response->output($session, Response::MODEL_SESSION)); + return $response->noContent(); } } @@ -2340,12 +2287,12 @@ App::patch('/v1/account/sessions/:sessionId') $provider = $session->getAttribute('provider'); $refreshToken = $session->getAttribute('providerRefreshToken'); - $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; - $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); - if (!\class_exists($className)) { + if (! \class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } @@ -2356,7 +2303,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(''))); $dbForProject->updateDocument('sessions', $sessionId, $session); @@ -2369,8 +2316,7 @@ App::patch('/v1/account/sessions/:sessionId') $events ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()) - ->setPayload($response->output($session, Response::MODEL_SESSION)) - ; + ->setPayload($response->output($session, Response::MODEL_SESSION)); return $response->dynamic($session, Response::MODEL_SESSION); } @@ -2400,29 +2346,27 @@ App::delete('/v1/account/sessions') ->inject('locale') ->inject('events') ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $events) { - $protocol = $request->getProtocol(); $sessions = $user->getAttribute('sessions', []); foreach ($sessions as $session) {/** @var Document $session */ $dbForProject->deleteDocument('sessions', $session->getId()); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([])); } $session ->setAttribute('current', false) - ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) - ; + ->setAttribute('countryName', $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))); if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { $session->setAttribute('current', true); $session->setAttribute('expire', DateTime::addSeconds(new \DateTime($session->getCreatedAt()), Auth::TOKEN_EXPIRATION_LOGIN_LONG)); - // If current session delete the cookies too + // If current session delete the cookies too $response - ->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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. @@ -2467,7 +2411,6 @@ App::post('/v1/account/recovery') ->inject('mails') ->inject('events') ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $mails, Event $events) { - if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -2482,7 +2425,7 @@ App::post('/v1/account/recovery') Query::equal('email', [$email]), ]); - if (!$profile) { + if (! $profile) { throw new Exception(Exception::USER_NOT_FOUND); } @@ -2523,12 +2466,12 @@ App::post('/v1/account/recovery') $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); - $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); - $subject = $locale->getText("emails.recovery.subject"); + $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); + $subject = $locale->getText('emails.recovery.subject'); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.recovery-' . $locale->default] ?? []; - if ($smtpEnabled && !empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.recovery-'.$locale->default] ?? []; + if ($smtpEnabled && ! empty($customTemplate)) { $body = $customTemplate['message'] ?? $body; $subject = $customTemplate['subject'] ?? $subject; $from = $customTemplate['senderName'] ?? $from; @@ -2536,13 +2479,13 @@ App::post('/v1/account/recovery') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText("emails.recovery.hello")) + ->setParam('{{hello}}', $locale->getText('emails.recovery.hello')) ->setParam('{{name}}', $profile->getAttribute('name')) - ->setParam('{{body}}', $locale->getText("emails.recovery.body")) + ->setParam('{{body}}', $locale->getText('emails.recovery.body')) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText("emails.recovery.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.recovery.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.recovery.signature")) + ->setParam('{{footer}}', $locale->getText('emails.recovery.footer')) + ->setParam('{{thanks}}', $locale->getText('emails.recovery.thanks')) + ->setParam('{{signature}}', $locale->getText('emails.recovery.signature')) ->setParam('{{project}}', $projectName) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -2551,7 +2494,6 @@ App::post('/v1/account/recovery') $body = $body->render(); - $mails ->setRecipient($profile->getAttribute('email', '')) ->setName($profile->getAttribute('name')) @@ -2559,7 +2501,6 @@ App::post('/v1/account/recovery') ->setFrom($from) ->setSubject($subject) ->trigger(); - ; $events ->setParam('userId', $profile->getId()) @@ -2568,8 +2509,7 @@ App::post('/v1/account/recovery') ->setPayload($response->output( $recovery->setAttribute('secret', $secret), Response::MODEL_TOKEN - )) - ; + )); // Hide secret for clients $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); @@ -2619,7 +2559,7 @@ App::put('/v1/account/recovery') $tokens = $profile->getAttribute('tokens', []); $recovery = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_RECOVERY, $secret); - if (!$recovery) { + if (! $recovery) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -2631,7 +2571,7 @@ App::put('/v1/account/recovery') $history = $profile->getAttribute('passwordHistory', []); if ($historyLimit > 0) { $validator = new PasswordHistory($history, $profile->getAttribute('hash'), $profile->getAttribute('hashOptions')); - if (!$validator->isValid($password)) { + if (! $validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -2660,8 +2600,7 @@ App::put('/v1/account/recovery') $events ->setParam('userId', $profile->getId()) - ->setParam('tokenId', $recoveryDocument->getId()) - ; + ->setParam('tokenId', $recoveryDocument->getId()); $response->dynamic($recoveryDocument, Response::MODEL_TOKEN); }); @@ -2682,7 +2621,7 @@ App::post('/v1/account/verification') ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') - ->param('url', '', fn($clients) => new Host($clients), '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, ['clients']) // TODO add built-in confirm page + ->param('url', '', fn ($clients) => new Host($clients), '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, ['clients']) // TODO add built-in confirm page ->inject('request') ->inject('response') ->inject('project') @@ -2692,7 +2631,6 @@ App::post('/v1/account/verification') ->inject('events') ->inject('mails') ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $events, Mail $mails) { - if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -2731,12 +2669,12 @@ App::post('/v1/account/verification') $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); - $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); - $subject = $locale->getText("emails.verification.subject"); + $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); + $subject = $locale->getText('emails.verification.subject'); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? []; - if ($smtpEnabled && !empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.verification-'.$locale->default] ?? []; + if ($smtpEnabled && ! empty($customTemplate)) { $body = $customTemplate['message'] ?? $body; $subject = $customTemplate['subject'] ?? $subject; $from = $customTemplate['senderName'] ?? $from; @@ -2744,13 +2682,13 @@ App::post('/v1/account/verification') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText("emails.verification.hello")) + ->setParam('{{hello}}', $locale->getText('emails.verification.hello')) ->setParam('{{name}}', $user->getAttribute('name')) - ->setParam('{{body}}', $locale->getText("emails.verification.body")) + ->setParam('{{body}}', $locale->getText('emails.verification.body')) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText("emails.verification.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.verification.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.verification.signature")) + ->setParam('{{footer}}', $locale->getText('emails.verification.footer')) + ->setParam('{{thanks}}', $locale->getText('emails.verification.thanks')) + ->setParam('{{signature}}', $locale->getText('emails.verification.signature')) ->setParam('{{project}}', $projectName) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -2765,8 +2703,7 @@ App::post('/v1/account/verification') ->setFrom($from) ->setRecipient($user->getAttribute('email')) ->setName($user->getAttribute('name') ?? '') - ->trigger() - ; + ->trigger(); $events ->setParam('userId', $user->getId()) @@ -2774,8 +2711,7 @@ App::post('/v1/account/verification') ->setPayload($response->output( $verification->setAttribute('secret', $verificationSecret), Response::MODEL_TOKEN - )) - ; + )); // Hide secret for clients $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); @@ -2808,8 +2744,7 @@ App::put('/v1/account/verification') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $events) { - - $profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); + $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -2818,7 +2753,7 @@ App::put('/v1/account/verification') $tokens = $profile->getAttribute('tokens', []); $verification = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_VERIFICATION, $secret); - if (!$verification) { + if (! $verification) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -2839,8 +2774,7 @@ App::put('/v1/account/verification') $events ->setParam('userId', $userId) - ->setParam('tokenId', $verificationDocument->getId()) - ; + ->setParam('tokenId', $verificationDocument->getId()); $response->dynamic($verificationDocument, Response::MODEL_TOKEN); }); @@ -2870,7 +2804,6 @@ App::post('/v1/account/verification/phone') ->inject('project') ->inject('locale') ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $events, EventPhone $messaging, Document $project, Locale $locale) { - if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED); } @@ -2907,10 +2840,10 @@ App::post('/v1/account/verification/phone') $dbForProject->deleteCachedDocument('users', $user->getId()); - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); + $message = Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.verification-' . $locale->default] ?? []; - if (!empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['sms.verification-'.$locale->default] ?? []; + if (! empty($customTemplate)) { $message = $customTemplate['message'] ?? $message; } @@ -2920,8 +2853,7 @@ App::post('/v1/account/verification/phone') $messaging ->setRecipient($user->getAttribute('phone')) ->setMessage($message) - ->trigger() - ; + ->trigger(); $events ->setParam('userId', $user->getId()) @@ -2929,8 +2861,7 @@ App::post('/v1/account/verification/phone') ->setPayload($response->output( $verification->setAttribute('secret', $secret), Response::MODEL_TOKEN - )) - ; + )); // Hide secret for clients $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); @@ -2963,8 +2894,7 @@ App::put('/v1/account/verification/phone') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $events) { - - $profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); + $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -2972,7 +2902,7 @@ App::put('/v1/account/verification/phone') $verification = Auth::phoneTokenVerify($user->getAttribute('tokens', []), $secret); - if (!$verification) { + if (! $verification) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -2992,8 +2922,7 @@ App::put('/v1/account/verification/phone') $events ->setParam('userId', $user->getId()) - ->setParam('tokenId', $verificationDocument->getId()) - ; + ->setParam('tokenId', $verificationDocument->getId()); $response->dynamic($verificationDocument, Response::MODEL_TOKEN); }); @@ -3032,7 +2961,7 @@ App::post('/v1/account/targets') $target = $dbForProject->getDocument('targets', $targetId); - if (!$target->isEmpty()) { + if (! $target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); } @@ -3040,7 +2969,7 @@ App::post('/v1/account/targets') '$id' => $targetId, // TO DO: what permissions should be given when created a target. '$permissions' => [ - Permission::read(Role::any()) + Permission::read(Role::any()), ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), @@ -3076,7 +3005,6 @@ App::patch('/v1/account/targets/:targetId/identifier') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -3121,7 +3049,6 @@ App::delete('/v1/account/targets/:targetId') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 0be2e0d849..047d99823e 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -1,7 +1,6 @@ output($output, $quality); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') ->setContentType('image/png') ->file($data); unset($image); @@ -83,12 +82,12 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro $accessTokenExpiry = $gitHubSession->getAttribute('providerAccessTokenExpiry'); $refreshToken = $gitHubSession->getAttribute('providerRefreshToken'); - $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; - $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); - if (!\class_exists($className)) { + if (! \class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } @@ -105,13 +104,13 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro $verificationId = $oauth2->getUserID($accessToken); if (empty($verificationId)) { - throw new \Exception("Locked tokens."); // Race codition, handeled in catch + throw new \Exception('Locked tokens.'); // Race codition, handeled in catch } $gitHubSession ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $oauth2->getAccessTokenExpiry(''))); Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); @@ -150,7 +149,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro return [ 'name' => $githubUser, - 'id' => $githubId + 'id' => $githubId, ]; } catch (Exception $error) { if ($logger) { @@ -177,7 +176,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('GitHub error log pushed with status code: ' . $responseCode); + Console::info('GitHub error log pushed with status code: '.$responseCode); } Console::warning("Failed: {$error->getMessage()}"); @@ -202,12 +201,12 @@ App::get('/v1/avatars/credit-cards/:code') ->label('sdk.description', '/docs/references/avatars/get-credit-card.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) - ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.') + ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true) ->inject('response') - ->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('credit-cards', $code, $width, $height, $quality, $response)); + ->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('credit-cards', $code, $width, $height, $quality, $response)); App::get('/v1/avatars/browsers/:code') ->desc('Get Browser Icon') @@ -267,18 +266,17 @@ App::get('/v1/avatars/image') ->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.', true) ->inject('response') ->action(function (string $url, int $width, int $height, Response $response) { - $quality = 80; $output = 'png'; $type = 'png'; - if (!\extension_loaded('imagick')) { + if (! \extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } $fetch = @\file_get_contents($url, false); - if (!$fetch) { + if (! $fetch) { throw new Exception(Exception::AVATAR_IMAGE_NOT_FOUND); } @@ -293,7 +291,7 @@ App::get('/v1/avatars/image') $data = $image->output($output, $quality); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') ->setContentType('image/png') ->file($data); unset($image); @@ -315,14 +313,13 @@ App::get('/v1/avatars/favicon') ->param('url', '', new URL(['http', 'https']), 'Website URL which you want to fetch the favicon from.') ->inject('response') ->action(function (string $url, Response $response) { - $width = 56; $height = 56; $quality = 80; $output = 'png'; $type = 'png'; - if (!\extension_loaded('imagick')) { + if (! \extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } @@ -344,7 +341,7 @@ App::get('/v1/avatars/favicon') \curl_close($curl); - if (!$html) { + if (! $html) { throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); } @@ -395,7 +392,7 @@ App::get('/v1/avatars/favicon') if (empty($outputHref) || empty($outputExt)) { $default = \parse_url($url); - $outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico'; + $outputHref = $default['scheme'].'://'.$default['host'].'/favicon.ico'; $outputExt = 'ico'; } @@ -406,14 +403,14 @@ App::get('/v1/avatars/favicon') throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found'); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') ->setContentType('image/x-icon') ->file($data); } $fetch = @\file_get_contents($outputHref, false); - if (!$fetch) { + if (! $fetch) { throw new Exception(Exception::AVATAR_ICON_NOT_FOUND); } @@ -423,7 +420,7 @@ App::get('/v1/avatars/favicon') $data = $image->output($output, $quality); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') ->setContentType('image/png') ->file($data); unset($image); @@ -446,7 +443,6 @@ App::get('/v1/avatars/qr') ->param('download', false, new Boolean(true), 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true) ->inject('response') ->action(function (string $text, int $size, int $margin, bool $download, Response $response) { - $download = ($download === '1' || $download === 'true' || $download === 1 || $download === true); $options = new QROptions([ 'addQuietzone' => true, @@ -464,7 +460,7 @@ App::get('/v1/avatars/qr') $image->crop((int) $size, (int) $size); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->setContentType('image/png') ->send($image->output('png', 9)); }); @@ -488,17 +484,16 @@ App::get('/v1/avatars/initials') ->inject('response') ->inject('user') ->action(function (string $name, int $width, int $height, string $background, Response $response, Document $user) { - $themes = [ ['background' => '#FFA1CE'], // Default (Pink) ['background' => '#FDC584'], // Orange ['background' => '#94DBD1'], // Green ['background' => '#A1C4FF'], // Blue ['background' => '#FFA1CE'], // Pink - ['background' => '#CBB1FC'] // Purple + ['background' => '#CBB1FC'], // Purple ]; - $name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', '')); + $name = (! empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', '')); $words = \explode(' ', \strtoupper($name)); // if there is no space, try to split by `_` underscore $words = (count($words) == 1) ? \explode('_', \strtoupper($name)) : $words; @@ -520,7 +515,7 @@ App::get('/v1/avatars/initials') // Wrap rand value to avoid out of range $rand = ($rand > \count($themes) - 1) ? $rand % \count($themes) : $rand; - $background = (!empty($background)) ? '#' . $background : $themes[$rand]['background']; + $background = (! empty($background)) ? '#'.$background : $themes[$rand]['background']; $image = new \Imagick(); $punch = new \Imagick(); @@ -529,8 +524,8 @@ App::get('/v1/avatars/initials') $punch->newImage($width, $height, 'transparent'); - $draw->setFont(__DIR__ . "/../../assets/fonts/poppins-v9-latin-500.ttf"); - $image->setFont(__DIR__ . "/../../assets/fonts/poppins-v9-latin-500.ttf"); + $draw->setFont(__DIR__.'/../../assets/fonts/poppins-v9-latin-500.ttf'); + $image->setFont(__DIR__.'/../../assets/fonts/poppins-v9-latin-500.ttf'); $draw->setFillColor(new ImagickPixel('black')); $draw->setFontSize($fontSize); @@ -542,13 +537,13 @@ App::get('/v1/avatars/initials') $punch->negateImage(true, Imagick::CHANNEL_ALPHA); $image->newImage($width, $height, $background); - $image->setImageFormat("png"); + $image->setImageFormat('png'); $image->compositeImage($punch, Imagick::COMPOSITE_COPYOPACITY, 0, 0); //$image->setImageCompressionQuality(9 - round(($quality / 100) * 9)); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->setContentType('image/png') ->file($image->getImageBlob()); }); @@ -582,7 +577,7 @@ App::get('/v1/cards/cloud') throw new Exception(Exception::USER_NOT_FOUND); } - if (!$mock) { + if (! $mock) { $name = $user->getAttribute('name', 'Anonymous'); $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); @@ -602,9 +597,9 @@ App::get('/v1/cards/cloud') $createdAt = new \DateTime($employees[$email]['memberSince'] ?? ''); } - if (!$isEmployee && !empty($githubName)) { + if (! $isEmployee && ! empty($githubName)) { $employeeGitHub = \array_search(\strtolower($githubName), \array_map(fn ($employee) => \strtolower($employee['gitHub']) ?? '', $employees)); - if (!empty($employeeGitHub)) { + if (! empty($employeeGitHub)) { $isEmployee = true; $employeeNumber = $isEmployee ? $employees[$employeeGitHub]['spot'] : ''; $createdAt = new \DateTime($employees[$employeeGitHub]['memberSince'] ?? ''); @@ -645,20 +640,20 @@ App::get('/v1/cards/cloud') $isGolden = $isEmployee || $isHero || $isContributor; $isPlatinum = $isGolden ? false : $isPlatinum; - $memberSince = \strtoupper('Member since ' . $createdAt->format('M') . ' ' . $createdAt->format('d') . ', ' . $createdAt->format('o')); + $memberSince = \strtoupper('Member since '.$createdAt->format('M').' '.$createdAt->format('d').', '.$createdAt->format('o')); $imagePath = $isGolden ? 'front-golden.png' : ($isPlatinum ? 'front-platinum.png' : 'front.png'); - $baseImage = new \Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $imagePath); + $baseImage = new \Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$imagePath); if ($isEmployee) { - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/employee.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/employee.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 793, 35); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); $text->setFillColor(new \ImagickPixel('#FFFADF')); $text->setFontSize(\strlen($employeeNumber) <= 2 ? 54 : 48); $text->setFontWeight(700); @@ -666,7 +661,7 @@ App::get('/v1/cards/cloud') $hashtag = new \ImagickDraw(); $hashtag->setTextAlignment(Imagick::ALIGN_CENTER); - $hashtag->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); + $hashtag->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); $hashtag->setFillColor(new \ImagickPixel('#FFFADF')); $hashtag->setFontSize(28); $hashtag->setFontWeight(700); @@ -689,25 +684,25 @@ App::get('/v1/cards/cloud') } if ($isContributor) { - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/contributor.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/contributor.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 793, 34); } if ($isHero) { - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/hero.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/hero.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 793, 34); } - setlocale(LC_ALL, "en_US.utf8"); + setlocale(LC_ALL, 'en_US.utf8'); // $name = \iconv("utf-8", "ascii//TRANSLIT", $name); // $memberSince = \iconv("utf-8", "ascii//TRANSLIT", $memberSince); // $githubName = \iconv("utf-8", "ascii//TRANSLIT", $githubName); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__ . '/../../../public/fonts/Poppins-Bold.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/Poppins-Bold.ttf'); $text->setFillColor(new \ImagickPixel('#FFFFFF')); if (\strlen($name) > 32) { @@ -726,17 +721,17 @@ App::get('/v1/cards/cloud') $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__ . '/../../../public/fonts/Inter-SemiBold.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/Inter-SemiBold.ttf'); $text->setFillColor(new \ImagickPixel($isGolden || $isPlatinum ? '#FFFFFF' : '#FFB9CC')); $text->setFontSize(27); $text->setFontWeight(600); $text->setTextKerning(1.08); $baseImage->annotateImage($text, 512, 541, 0, \strtoupper($memberSince)); - if (!empty($githubName)) { + if (! empty($githubName)) { $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Regular.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/Inter-Regular.ttf'); $text->setFillColor(new \ImagickPixel('#FFFFFF')); $text->setFontSize($scalingDown ? 28 : 32); $text->setFontWeight(400); @@ -744,18 +739,18 @@ App::get('/v1/cards/cloud') $baseImage->annotateImage($text, 512 + 20 + 4, 373 + ($scalingDown ? 2 : 0), 0, $githubName); - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $precisionFix = 5; $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 512 - ($metrics['textWidth'] / 2) - 20 - 4, 373 - ($metrics['textHeight'] - $precisionFix)); } - if (!empty($width) || !empty($height)) { + if (! empty($width) || ! empty($height)) { $baseImage->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->setContentType('image/png') ->file($baseImage->getImageBlob()); }); @@ -789,7 +784,7 @@ App::get('/v1/cards/cloud-back') throw new Exception(Exception::USER_NOT_FOUND); } - if (!$mock) { + if (! $mock) { $userId = $user->getId(); $email = $user->getAttribute('email', ''); @@ -809,31 +804,31 @@ App::get('/v1/cards/cloud-back') $isPlatinum = $mock === 'platinum'; } - $userId = 'UID ' . $userId; + $userId = 'UID '.$userId; $isPlatinum = $isGolden ? false : $isPlatinum; $imagePath = $isGolden ? 'back-golden.png' : ($isPlatinum ? 'back-platinum.png' : 'back.png'); - $baseImage = new \Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $imagePath); + $baseImage = new \Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$imagePath); - setlocale(LC_ALL, "en_US.utf8"); + setlocale(LC_ALL, 'en_US.utf8'); // $userId = \iconv("utf-8", "ascii//TRANSLIT", $userId); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__ . '/../../../public/fonts/SourceCodePro-Regular.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/SourceCodePro-Regular.ttf'); $text->setFillColor(new \ImagickPixel($isGolden ? '#664A1E' : ($isPlatinum ? '#555555' : '#E8E9F0'))); $text->setFontSize(28); $text->setFontWeight(400); $baseImage->annotateImage($text, 512, 596, 0, $userId); - if (!empty($width) || !empty($height)) { + if (! empty($width) || ! empty($height)) { $baseImage->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->setContentType('image/png') ->file($baseImage->getImageBlob()); }); @@ -867,7 +862,7 @@ App::get('/v1/cards/cloud-og') throw new Exception(Exception::USER_NOT_FOUND); } - if (!$mock) { + if (! $mock) { $internalId = $user->getInternalId(); $bgVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); $cardVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); @@ -891,9 +886,9 @@ App::get('/v1/cards/cloud-og') $createdAt = new \DateTime($employees[$email]['memberSince'] ?? ''); } - if (!$isEmployee && !empty($githubName)) { + if (! $isEmployee && ! empty($githubName)) { $employeeGitHub = \array_search(\strtolower($githubName), \array_map(fn ($employee) => \strtolower($employee['gitHub']) ?? '', $employees)); - if (!empty($employeeGitHub)) { + if (! empty($employeeGitHub)) { $isEmployee = true; $employeeNumber = $isEmployee ? $employees[$employeeGitHub]['spot'] : ''; $createdAt = new \DateTime($employees[$employeeGitHub]['memberSince'] ?? ''); @@ -940,17 +935,17 @@ App::get('/v1/cards/cloud-og') $isGolden = $isEmployee || $isHero || $isContributor; $isPlatinum = $isGolden ? false : $isPlatinum; - $memberSince = \strtoupper('Member since ' . $createdAt->format('M') . ' ' . $createdAt->format('d') . ', ' . $createdAt->format('o')); + $memberSince = \strtoupper('Member since '.$createdAt->format('M').' '.$createdAt->format('d').', '.$createdAt->format('o')); - $baseImage = new \Imagick(__DIR__ . "/../../../public/images/cards/cloud/og-background{$bgVariation}.png"); + $baseImage = new \Imagick(__DIR__."/../../../public/images/cards/cloud/og-background{$bgVariation}.png"); $cardType = $isGolden ? '-golden' : ($isPlatinum ? '-platinum' : ''); - $image = new Imagick(__DIR__ . "/../../../public/images/cards/cloud/og-card{$cardType}{$cardVariation}.png"); + $image = new Imagick(__DIR__."/../../../public/images/cards/cloud/og-card{$cardType}{$cardVariation}.png"); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 1008 / 2 - $image->getImageWidth() / 2, 1008 / 2 - $image->getImageHeight() / 2); - $imageLogo = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/og-background-logo.png'); - $imageShadow = new Imagick(__DIR__ . "/../../../public/images/cards/cloud/og-shadow{$cardType}.png"); + $imageLogo = new Imagick(__DIR__.'/../../../public/images/cards/cloud/og-background-logo.png'); + $imageShadow = new Imagick(__DIR__."/../../../public/images/cards/cloud/og-shadow{$cardType}.png"); if ($cardVariation === '1') { $baseImage->compositeImage($imageLogo, Imagick::COMPOSITE_OVER, 32, 1008 - $imageLogo->getImageHeight() - 32); $baseImage->compositeImage($imageShadow, Imagick::COMPOSITE_OVER, -450, 700); @@ -964,19 +959,19 @@ App::get('/v1/cards/cloud-og') if ($isEmployee) { $file = $cardVariation === '3' ? 'employee-skew.png' : 'employee.png'; - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $file); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$file); $image->setGravity(Imagick::GRAVITY_CENTER); $hashtag = new \ImagickDraw(); $hashtag->setTextAlignment(Imagick::ALIGN_LEFT); - $hashtag->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); + $hashtag->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); $hashtag->setFillColor(new \ImagickPixel('#FFFADF')); $hashtag->setFontSize(20); $hashtag->setFontWeight(700); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_LEFT); - $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); $text->setFillColor(new \ImagickPixel('#FFFADF')); $text->setFontSize(\strlen($employeeNumber) <= 1 ? 36 : 28); $text->setFontWeight(700); @@ -1050,7 +1045,7 @@ App::get('/v1/cards/cloud-og') if ($isContributor) { $file = $cardVariation === '3' ? 'contributor-skew.png' : 'contributor.png'; - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $file); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$file); $image->setGravity(Imagick::GRAVITY_CENTER); if ($cardVariation === '1') { @@ -1068,7 +1063,7 @@ App::get('/v1/cards/cloud-og') if ($isHero) { $file = $cardVariation === '3' ? 'hero-skew.png' : 'hero.png'; - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $file); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$file); $image->setGravity(Imagick::GRAVITY_CENTER); if ($cardVariation === '1') { @@ -1084,14 +1079,14 @@ App::get('/v1/cards/cloud-og') } } - setlocale(LC_ALL, "en_US.utf8"); + setlocale(LC_ALL, 'en_US.utf8'); // $name = \iconv("utf-8", "ascii//TRANSLIT", $name); // $memberSince = \iconv("utf-8", "ascii//TRANSLIT", $memberSince); // $githubName = \iconv("utf-8", "ascii//TRANSLIT", $githubName); $textName = new \ImagickDraw(); $textName->setTextAlignment(Imagick::ALIGN_CENTER); - $textName->setFont(__DIR__ . '/../../../public/fonts/Poppins-Bold.ttf'); + $textName->setFont(__DIR__.'/../../../public/fonts/Poppins-Bold.ttf'); $textName->setFillColor(new \ImagickPixel('#FFFFFF')); if (\strlen($name) > 32) { @@ -1128,7 +1123,7 @@ App::get('/v1/cards/cloud-og') $textMember = new \ImagickDraw(); $textMember->setTextAlignment(Imagick::ALIGN_CENTER); - $textMember->setFont(__DIR__ . '/../../../public/fonts/Inter-Medium.ttf'); + $textMember->setFont(__DIR__.'/../../../public/fonts/Inter-Medium.ttf'); $textMember->setFillColor(new \ImagickPixel($isGolden || $isPlatinum ? '#FFFFFF' : '#FFB9CC')); $textMember->setFontWeight(500); $textMember->setTextKerning(1.12); @@ -1158,10 +1153,10 @@ App::get('/v1/cards/cloud-og') $baseImage->drawImage($textMember); } - if (!empty($githubName)) { + if (! empty($githubName)) { $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_LEFT); - $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Regular.ttf'); + $text->setFont(__DIR__.'/../../../public/fonts/Inter-Regular.ttf'); $text->setFillColor(new \ImagickPixel('#FFFFFF')); $text->setFontSize($scalingDown ? 16 : 20); $text->setFontWeight(400); @@ -1172,7 +1167,7 @@ App::get('/v1/cards/cloud-og') $group = new Imagick(); $groupWidth = $metrics['textWidth'] + 32 + 4; $group->newImage($groupWidth, $metrics['textHeight'] + 10, '#00000000'); - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $image->resizeImage(32, 32, Imagick::FILTER_LANCZOS, 1); $precisionFix = -1; @@ -1190,7 +1185,7 @@ App::get('/v1/cards/cloud-og') $group = new Imagick(); $groupWidth = $metrics['textWidth'] + 32 + 4; $group->newImage($groupWidth, $metrics['textHeight'] + 10, '#00000000'); - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $image->resizeImage(32, 32, Imagick::FILTER_LANCZOS, 1); $precisionFix = -1; @@ -1210,7 +1205,7 @@ App::get('/v1/cards/cloud-og') $text->annotation(320 + 15 + 2, 640, $githubName); $metrics = $baseImage->queryFontMetrics($text, $githubName); - $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github-skew.png'); + $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github-skew.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 512 - ($metrics['textWidth'] / 2), 518 + \strlen($githubName) * 1.3); @@ -1218,12 +1213,12 @@ App::get('/v1/cards/cloud-og') } } - if (!empty($width) || !empty($height)) { + if (! empty($width) || ! empty($height)) { $baseImage->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->setContentType('image/png') ->file($baseImage->getImageBlob()); }); diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index f2ea83af58..846964cad6 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -15,7 +15,6 @@ App::init() } }); - App::get('/v1/console/variables') ->desc('Get Variables') ->groups(['api', 'projects']) @@ -29,7 +28,6 @@ App::get('/v1/console/variables') ->label('sdk.response.model', Response::MODEL_CONSOLE_VARIABLES) ->inject('response') ->action(function (Response $response) { - $variables = new Document([ '_APP_DOMAIN_TARGET' => App::getEnv('_APP_DOMAIN_TARGET'), '_APP_STORAGE_LIMIT' => +App::getEnv('_APP_STORAGE_LIMIT'), @@ -40,7 +38,6 @@ App::get('/v1/console/variables') $response->dynamic($variables, Response::MODEL_CONSOLE_VARIABLES); }); - App::post('/v1/console/assistant') ->desc('Ask Query') ->groups(['api', 'assistant']) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index aa7999b844..8f1868f17e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -17,9 +17,7 @@ use MaxMind\Db\Reader; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; -use Utopia\Database\Adapter\MariaDB; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate as DuplicateException; @@ -46,8 +44,8 @@ use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; -use Utopia\Validator\IP; use Utopia\Validator\Integer; +use Utopia\Validator\IP; use Utopia\Validator\JSON; use Utopia\Validator\Nullable; use Utopia\Validator\Range; @@ -60,6 +58,7 @@ use Utopia\Validator\WhiteList; * * * @return Document Newly created attribute document + * * @throws Exception */ function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $database, Event $events): Document @@ -82,14 +81,14 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (!empty($format)) { - if (!Structure::hasFormat($format, $type)) { + if (! empty($format)) { + if (! Structure::hasFormat($format, $type)) { throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} attributes."); } } @@ -105,7 +104,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); + $relatedCollection = $dbForProject->getDocument('database_'.$db->getInternalId(), $options['relatedCollection'] ?? ''); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related collection was not found.'); } @@ -113,7 +112,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $attribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($db->getInternalId().'_'.$collection->getInternalId().'_'.$key), 'key' => $key, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), @@ -139,13 +138,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); } catch (\Exception $e) { - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$collection->getInternalId()); throw $e; } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$collection->getInternalId()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -155,7 +154,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), + '$id' => ID::custom($db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$twoWayKey), 'key' => $twoWayKey, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), @@ -183,13 +182,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); } catch (\Exception $e) { - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$relatedCollection->getInternalId()); throw $e; } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$relatedCollection->getInternalId()); } $database @@ -231,13 +230,13 @@ function updateAttribute( throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -263,7 +262,7 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); } - $collectionId = 'database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId(); + $collectionId = 'database_'.$db->getInternalId().'_collection_'.$collection->getInternalId(); $attribute ->setAttribute('default', $default) @@ -287,18 +286,18 @@ function updateAttribute( } else { $validator = new Range($min, $max, Database::VAR_FLOAT); - if (!is_null($default)) { + if (! is_null($default)) { $default = \floatval($default); } } - if (!is_null($default) && !$validator->isValid($default)) { + if (! is_null($default) && ! $validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } $options = [ 'min' => $min, - 'max' => $max + 'max' => $max, ]; $attribute->setAttribute('formatOptions', $options); @@ -314,12 +313,12 @@ function updateAttribute( } } - if (!is_null($default) && !in_array($default, $elements)) { + if (! is_null($default) && ! in_array($default, $elements)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); } $options = [ - 'elements' => $elements + 'elements' => $elements, ]; $attribute->setAttribute('formatOptions', $options); @@ -338,13 +337,13 @@ function updateAttribute( ); if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_'.$db->getInternalId(), $primaryDocumentOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$primaryDocumentOptions['twoWayKey']); $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->updateDocument('attributes', $db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $relatedCollection->getId()); } } else { $dbForProject->updateAttribute( @@ -356,8 +355,8 @@ function updateAttribute( ); } - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collection->getId()); + $dbForProject->updateDocument('attributes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key, $attribute); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collection->getId()); $events ->setContext('collection', $collection) @@ -390,7 +389,6 @@ App::post('/v1/databases') ->inject('dbForProject') ->inject('events') ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $events) { - $databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId; try { @@ -420,7 +418,7 @@ App::post('/v1/databases') 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' + 'format' => $attribute['format'] ?? '', ]); } @@ -433,7 +431,7 @@ App::post('/v1/databases') 'orders' => $index['orders'], ]); } - $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); + $dbForProject->createCollection('database_'.$database->getInternalId(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); } @@ -456,15 +454,14 @@ App::get('/v1/databases') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DATABASE_LIST) - ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -505,7 +502,6 @@ App::get('/v1/databases/:databaseId') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, Response $response, Database $dbForProject) { - $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -533,7 +529,6 @@ App::get('/v1/databases/:databaseId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -546,13 +541,13 @@ App::get('/v1/databases/:databaseId/logs') $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId; + $resource = 'database/'.$databaseId; $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -580,14 +575,14 @@ App::get('/v1/databases/:databaseId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'deviceModel' => $device['deviceModel'], ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -600,7 +595,6 @@ App::get('/v1/databases/:databaseId/logs') ]), Response::MODEL_LOG_LIST); }); - App::put('/v1/databases/:databaseId') ->desc('Update Database') ->groups(['api', 'database', 'schema']) @@ -622,7 +616,6 @@ App::put('/v1/databases/:databaseId') ->inject('dbForProject') ->inject('events') ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $events) { - $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -637,7 +630,7 @@ App::put('/v1/databases/:databaseId') } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage()); + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. '.$exception->getMessage()); } $events->setParam('databaseId', $database->getId()); @@ -664,19 +657,18 @@ App::delete('/v1/databases/:databaseId') ->inject('events') ->inject('deletes') ->action(function (string $databaseId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { - $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - if (!$dbForProject->deleteDocument('databases', $databaseId)) { + if (! $dbForProject->deleteDocument('databases', $databaseId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } $dbForProject->deleteCachedDocument('databases', $database->getId()); - $dbForProject->deleteCachedCollection('databases_' . $database->getInternalId()); + $dbForProject->deleteCachedCollection('databases_'.$database->getInternalId()); $deletes ->setType(DELETE_TYPE_DOCUMENT) @@ -715,10 +707,9 @@ App::post('/v1/databases/:databaseId/collections') ->inject('mode') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $events) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } @@ -728,7 +719,7 @@ App::post('/v1/databases/:databaseId/collections') $permissions = Permission::aggregate($permissions); try { - $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + $dbForProject->createDocument('database_'.$database->getInternalId(), new Document([ '$id' => $collectionId, 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $databaseId, @@ -738,9 +729,9 @@ App::post('/v1/databases/:databaseId/collections') 'name' => $name, 'search' => implode(' ', [$collectionId, $name]), ])); - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); - $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions ?? [], documentSecurity: $documentSecurity); + $dbForProject->createCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), permissions: $permissions ?? [], documentSecurity: $documentSecurity); } catch (DuplicateException) { throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); } catch (LimitException) { @@ -770,22 +761,21 @@ App::get('/v1/databases/:databaseId/collections') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_COLLECTION_LIST) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new 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) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -795,7 +785,7 @@ App::get('/v1/databases/:databaseId/collections') if ($cursor) { /** @var Query $cursor */ $collectionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $cursorDocument = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); @@ -807,8 +797,8 @@ App::get('/v1/databases/:databaseId/collections') $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ - 'collections' => $dbForProject->find('database_' . $database->getInternalId(), $queries), - 'total' => $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT), + 'collections' => $dbForProject->find('database_'.$database->getInternalId(), $queries), + 'total' => $dbForProject->count('database_'.$database->getInternalId(), $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_COLLECTION_LIST); }); @@ -830,14 +820,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -866,14 +855,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_'.$database->getInternalId().'_collection_'.$collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -885,13 +873,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/collection/' . $collectionId; + $resource = 'database/'.$databaseId.'/collection/'.$collectionId; $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -919,14 +907,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'deviceModel' => $device['deviceModel'], ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -939,7 +927,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ]), Response::MODEL_LOG_LIST); }); - App::put('/v1/databases/:databaseId/collections/:collectionId') ->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default']) ->desc('Update Collection') @@ -966,14 +953,13 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->inject('mode') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $events) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -987,17 +973,17 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') $enabled ??= $collection->getAttribute('enabled', true); try { - $collection = $dbForProject->updateDocument('database_' . $database->getInternalId(), $collectionId, $collection + $collection = $dbForProject->updateDocument('database_'.$database->getInternalId(), $collectionId, $collection ->setAttribute('name', $name) ->setAttribute('$permissions', $permissions) ->setAttribute('documentSecurity', $documentSecurity) ->setAttribute('enabled', $enabled) ->setAttribute('search', implode(' ', [$collectionId, $name]))); - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $permissions, $documentSecurity); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage()); + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. '.$exception->getMessage()); } $events @@ -1030,24 +1016,23 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') ->inject('events') ->inject('deletes') ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode, Event $events, Delete $deletes) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { + if (! $dbForProject->deleteDocument('database_'.$database->getInternalId(), $collectionId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCachedCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId()); $deletes ->setType(DELETE_TYPE_DOCUMENT) @@ -1090,10 +1075,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - // Ensure attribute default is within required size $validator = new Text($size, 0); - if (!is_null($default) && !$validator->isValid($default)) { + if (! is_null($default) && ! $validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1144,7 +1128,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, @@ -1178,7 +1161,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->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('key', '', new Key(), 'Attribute Key.') - ->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE, min: 0), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.') + ->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE, min: 0), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' elements are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long.') ->param('required', null, new Boolean(), 'Is attribute required?') ->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) ->param('array', false, new Boolean(), 'Is attribute an array?', true) @@ -1187,7 +1170,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - // use length of longest string as attribute size $size = 0; foreach ($elements as $element) { @@ -1198,7 +1180,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') $size = ($length > $size) ? $length : $size; } - if (!is_null($default) && !in_array($default, $elements)) { + if (! is_null($default) && ! in_array($default, $elements)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); } @@ -1244,7 +1226,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, @@ -1286,7 +1267,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, @@ -1330,7 +1310,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - // Ensure attribute default is within range $min = (is_null($min)) ? PHP_INT_MIN : \intval($min); $max = (is_null($max)) ? PHP_INT_MAX : \intval($max); @@ -1341,7 +1320,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege $validator = new Range($min, $max, Database::VAR_INTEGER); - if (!is_null($default) && !$validator->isValid($default)) { + if (! is_null($default) && ! $validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1363,7 +1342,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege $formatOptions = $attribute->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { + if (! empty($formatOptions)) { $attribute->setAttribute('min', \intval($formatOptions['min'])); $attribute->setAttribute('max', \intval($formatOptions['max'])); } @@ -1401,7 +1380,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - // Ensure attribute default is within range $min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min); $max = (is_null($max)) ? PHP_FLOAT_MAX : \floatval($max); @@ -1411,13 +1389,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' } // Ensure default value is a float - if (!is_null($default)) { + if (! is_null($default)) { $default = \floatval($default); } $validator = new Range($min, $max, Database::VAR_FLOAT); - if (!is_null($default) && !$validator->isValid($default)) { + if (! is_null($default) && ! $validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1437,7 +1415,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' $formatOptions = $attribute->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { + if (! empty($formatOptions)) { $attribute->setAttribute('min', \floatval($formatOptions['min'])); $attribute->setAttribute('max', \floatval($formatOptions['max'])); } @@ -1473,7 +1451,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_BOOLEAN, @@ -1514,7 +1491,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $filters[] = 'datetime'; $attribute = createAttribute($databaseId, $collectionId, new Document([ @@ -1593,7 +1569,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati 'twoWay' => $twoWay, 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, - ] + ], ]), $response, $dbForProject, @@ -1626,18 +1602,17 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' queries are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long. You may filter on the following attributes: '.implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1653,7 +1628,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') if ($cursor) { $attributeId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [ + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('attributes', [ Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$attributeId]), @@ -1694,27 +1669,26 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') Response::MODEL_ATTRIBUTE_IP, Response::MODEL_ATTRIBUTE_DATETIME, Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING])// needs to be last, since its condition would dominate any other string attribute + Response::MODEL_ATTRIBUTE_STRING, ])// needs to be last, since its condition would dominate any other string attribute ->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('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getInternalId().'_'.$collection->getInternalId().'_'.$key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -1770,7 +1744,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin ->inject('dbForProject') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) { - $attribute = updateAttribute( databaseId: $databaseId, collectionId: $collectionId, @@ -1842,7 +1815,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/ ->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('key', '', new Key(), 'Attribute Key.') - ->param('elements', null, new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.') + ->param('elements', null, new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' elements are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long.') ->param('required', null, new Boolean(), 'Is attribute required?') ->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.') ->inject('response') @@ -1984,7 +1957,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ $formatOptions = $attribute->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { + if (! empty($formatOptions)) { $attribute->setAttribute('min', \intval($formatOptions['min'])); $attribute->setAttribute('max', \intval($formatOptions['max'])); } @@ -2033,7 +2006,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float $formatOptions = $attribute->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { + if (! empty($formatOptions)) { $attribute->setAttribute('min', \floatval($formatOptions['min'])); $attribute->setAttribute('max', \floatval($formatOptions['max'])); } @@ -2157,7 +2130,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ type: Database::VAR_RELATIONSHIP, required: false, options: [ - 'onDelete' => $onDelete + 'onDelete' => $onDelete, ] ); @@ -2194,19 +2167,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - - $db = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2217,19 +2189,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$collection->getInternalId()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_'.$db->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$options['twoWayKey']); if ($relatedAttribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2239,8 +2211,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $options['relatedCollection']); + $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$relatedCollection->getInternalId()); } } @@ -2300,21 +2272,20 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->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('key', null, new Key(), 'Index Key.') ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL, Database::INDEX_ARRAY]), 'Index type.') - ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.') - ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) + ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' attributes are allowed, each 32 characters long.') + ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' orders are allowed.', true) ->inject('response') ->inject('dbForProject') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - - $db = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2322,7 +2293,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $count = $dbForProject->count('indexes', [ Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$db->getInternalId()]) + Query::equal('databaseInternalId', [$db->getInternalId()]), ], 61); $limit = $dbForProject->getLimitForIndexes(); @@ -2332,7 +2303,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } // Convert Document[] to array of attribute metadata - $oldAttributes = \array_map(fn($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); + $oldAttributes = \array_map(fn ($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); $oldAttributes[] = [ 'key' => '$id', @@ -2341,7 +2312,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'required' => true, 'array' => false, 'default' => null, - 'size' => 36 + 'size' => 36, ]; $oldAttributes[] = [ @@ -2352,7 +2323,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'required' => false, 'array' => false, 'default' => null, - 'size' => 0 + 'size' => 0, ]; $oldAttributes[] = [ @@ -2363,7 +2334,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'required' => false, 'array' => false, 'default' => null, - 'size' => 0 + 'size' => 0, ]; // lengths hidden by default @@ -2374,7 +2345,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key')); if ($attributeIndex === false) { - throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: ' . $attribute); + throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: '.$attribute); } $attributeStatus = $oldAttributes[$attributeIndex]['status']; @@ -2382,12 +2353,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $attributeSize = $oldAttributes[$attributeIndex]['size']; if ($attributeType === Database::VAR_RELATIONSHIP) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship attribute: ' . $oldAttributes[$attributeIndex]['key']); + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship attribute: '.$oldAttributes[$attributeIndex]['key']); } // ensure attribute is available if ($attributeStatus !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']); + throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: '.$oldAttributes[$attributeIndex]['key']); } // set attribute size as index length only for strings @@ -2395,7 +2366,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } $index = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($db->getInternalId().'_'.$collection->getInternalId().'_'.$key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck 'databaseInternalId' => $db->getInternalId(), @@ -2409,7 +2380,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ]); $validator = new IndexValidator($dbForProject->getAdapter()->getMaxIndexLength()); - if (!$validator->isValid($collection->setAttribute('indexes', $index, Document::SET_TYPE_APPEND))) { + if (! $validator->isValid($collection->setAttribute('indexes', $index, Document::SET_TYPE_APPEND))) { throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); } @@ -2419,7 +2390,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); $database ->setType(DATABASE_TYPE_CREATE_INDEX) @@ -2453,18 +2424,17 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->label('sdk.response.model', Response::MODEL_INDEX_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' queries are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long. You may filter on the following attributes: '.implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2473,17 +2443,17 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $queries = Query::parseQueries($queries); \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); - $cursor = reset($cursor); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); if ($cursor) { $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn() => $dbForProject->find('indexes', [ + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$indexId]), - Query::limit(1) + Query::limit(1), ])); if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { @@ -2518,13 +2488,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2538,7 +2507,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $response->dynamic($index, Response::MODEL_INDEX); }); - App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->alias('/v1/database/collections/:collectionId/indexes/:key', ['databaseId' => 'default']) ->desc('Delete Index') @@ -2561,19 +2529,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - - $db = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key); if (empty($index->getId())) { throw new Exception(Exception::INDEX_NOT_FOUND); @@ -2584,7 +2551,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); $database ->setType(DATABASE_TYPE_DELETE_INDEX) @@ -2634,7 +2601,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('events') ->inject('mode') ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $events, string $mode) { - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data)) { @@ -2645,16 +2611,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); } - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } @@ -2671,7 +2637,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') // Add permissions for current the user if none were provided. if (\is_null($permissions)) { $permissions = []; - if (!empty($user->getId())) { + if (! empty($user->getId())) { foreach ($allowedPermissions as $permission) { $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); } @@ -2680,7 +2646,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { + if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -2692,8 +2658,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + if (! Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); } } } @@ -2709,20 +2675,20 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $validator = new Authorization($permission); $valid = $validator->isValid($collection->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { + if (($permission === Database::PERMISSION_UPDATE && ! $documentSecurity) || ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } if ($permission === Database::PERMISSION_UPDATE) { $valid = $valid || $validator->isValid($document->getUpdate()); - if ($documentSecurity && !$valid) { + if ($documentSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } } $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -2742,21 +2708,21 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { if ( \is_array($relation) && \array_values($relation) !== $relation - && !isset($relation['$id']) + && ! isset($relation['$id']) ) { $relation['$id'] = ID::unique(); $relation = new Document($relation); } if ($relation instanceof Document) { $current = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId(), $relation->getId()) ); if ($current->isEmpty()) { @@ -2786,46 +2752,46 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $checkPermissions($collection, $document, Database::PERMISSION_CREATE); - try { - $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); - } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage()); - } catch (DuplicateException $exception) { - throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); - } + try { + $document = $dbForProject->createDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $document); + } catch (StructureException $exception) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage()); + } catch (DuplicateException $exception) { + throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (! \is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } } } - } - }; + }; $processDocument($collection, $document); @@ -2856,37 +2822,36 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') ->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 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('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) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - if (!$collection->getAttribute('documentSecurity', false)) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if (! $collection->getAttribute('documentSecurity', false)) { $validator = new Authorization(Database::PERMISSION_READ); - if (!$validator->isValid($collection->getRead())) { + if (! $validator->isValid($collection->getRead())) { $collection = new Document(); } } } - if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { + if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Validate queries $queriesValidator = new Documents($collection->getAttribute('attributes'), $collection->getAttribute('indexes')); $validQueries = $queriesValidator->isValid($queries); - if (!$validQueries) { + if (! $validQueries) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $queriesValidator->getDescription()); } @@ -2898,7 +2863,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') if ($cursor) { $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -2909,8 +2874,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $filterQueries = Query::groupByType($queries)['filters']; - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $queries); + $total = $dbForProject->count('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT); // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { @@ -2924,7 +2889,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -2933,18 +2898,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') if (empty($related)) { continue; } - if (!\is_array($related)) { + if (! \is_array($related)) { $relations = [$related]; } else { $relations = $related; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { - if (!$processDocument($relatedCollection, $doc)) { + if (! $processDocument($relatedCollection, $doc)) { unset($relations[$index]); } } @@ -2961,9 +2926,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') }; // The linter is forcing this indentation - foreach ($documents as $document) { - $processDocument($collection, $document); - } + foreach ($documents as $document) { + $processDocument($collection, $document); + } $response->dynamic(new Document([ 'total' => $total, @@ -2993,17 +2958,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } @@ -3011,13 +2975,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen // Validate queries $queriesValidator = new DocumentQueriesValidator($collection->getAttribute('attributes')); $validQueries = $queriesValidator->isValid($queries); - if (!$validQueries) { + if (! $validQueries) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $queriesValidator->getDescription()); } $queries = Query::parseQueries($queries); - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + $document = $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId, $queries); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3034,7 +2998,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3043,13 +3007,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen if (empty($related)) { continue; } - if (!\is_array($related)) { + if (! \is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3086,20 +3050,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->inject('locale') ->inject('geodb') ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + $document = $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3111,13 +3074,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId(); + $resource = 'database/'.$databaseId.'/collection/'.$collectionId.'/document/'.$document->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -3145,14 +3108,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'deviceModel' => $device['deviceModel'], ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -3195,30 +3158,29 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->inject('events') ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $events, string $mode) { - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data) && \is_null($permissions)) { throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); } - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } // Read permission should not be required for update /** @var Document $document */ - $document = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3233,7 +3195,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { + if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles) && ! \is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -3245,8 +3207,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + if (! Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); } } } @@ -3266,7 +3228,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) { $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3286,7 +3248,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -3294,14 +3256,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum if ( \is_array($relation) && \array_values($relation) !== $relation - && !isset($relation['$id']) + && ! isset($relation['$id']) ) { $relation['$id'] = ID::unique(); $relation = new Document($relation); } if ($relation instanceof Document) { - $oldDocument = Authorization::skip(fn() => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -3309,7 +3271,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId() ); if ($oldDocument->isEmpty()) { @@ -3334,8 +3296,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, - fn() => $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + fn () => $dbForProject->updateDocument( + 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $document->getId(), $newDocument ) @@ -3355,7 +3317,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3364,13 +3326,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum if (empty($related)) { continue; } - if (!\is_array($related)) { + if (! \is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3422,23 +3384,22 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('deletes') ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $events, Delete $deletes, string $mode) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } // Read permission should not be required for delete - $document = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3449,18 +3410,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $validator = new Authorization(Database::PERMISSION_DELETE); $valid = $validator->isValid($collection->getDelete()); - if (!$documentSecurity && !$valid) { + if (! $documentSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $valid = $valid || $validator->isValid($document->getDelete()); - if ($documentSecurity && !$valid) { + if ($documentSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3469,13 +3430,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu if (empty($related)) { continue; } - if (!\is_array($related)) { + if (! \is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3491,10 +3452,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $checkPermissions($collection, $document); - Authorization::skip(fn() => $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { + Authorization::skip(fn () => $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { try { $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId ); } catch (RestrictedException) { @@ -3503,7 +3464,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu })); $dbForProject->deleteCachedDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId ); @@ -3514,7 +3475,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3523,13 +3484,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu if (empty($related)) { continue; } - if (!\is_array($related)) { + if (! \is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3571,7 +3532,6 @@ App::get('/v1/databases/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { - $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -3605,23 +3565,23 @@ App::get('/v1/databases/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } $response->dynamic(new Document([ 'range' => $range, - 'databasesTotal' => $usage[$metrics[0]], + 'databasesTotal' => $usage[$metrics[0]], 'collectionsTotal' => $usage[$metrics[1]], - 'documentsTotal' => $usage[$metrics[2]], + 'documentsTotal' => $usage[$metrics[2]], ]), Response::MODEL_USAGE_DATABASES); }); @@ -3640,8 +3600,7 @@ App::get('/v1/databases/:databaseId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) { - - $database = $dbForProject->getDocument('databases', $databaseId); + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -3679,23 +3638,23 @@ App::get('/v1/databases/:databaseId/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } $response->dynamic(new Document([ 'range' => $range, - 'collectionsTotal' => $usage[$metrics[0]], - 'documentsTotal' => $usage[$metrics[1]], + 'collectionsTotal' => $usage[$metrics[0]], + 'documentsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_DATABASE); }); @@ -3716,10 +3675,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { - - $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $database = $dbForProject->getDocument('databases', $databaseId); + $collectionDocument = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_'.$database->getInternalId().'_collection_'.$collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3756,21 +3714,21 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } $response->dynamic(new Document([ 'range' => $range, - 'documentsTotal' => $usage[$metrics[0]], + 'documentsTotal' => $usage[$metrics[0]], ]), Response::MODEL_USAGE_COLLECTION); }); diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 81500f1d27..b7baf560bb 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -9,40 +9,40 @@ use Appwrite\Event\Func; use Appwrite\Event\Usage; use Appwrite\Event\Validator\Event as ValidatorEvent; use Appwrite\Extend\Exception; +use Appwrite\Task\Validator\Cron; use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Database\Validator\Queries\Deployments; +use Appwrite\Utopia\Database\Validator\Queries\Executions; +use Appwrite\Utopia\Database\Validator\Queries\Functions; +use Appwrite\Utopia\Response; +use Executor\Executor; +use Utopia\App; +use Utopia\CLI\Console; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Roles; use Utopia\Database\Validator\UID; use Utopia\Storage\Device; use Utopia\Storage\Validator\File; use Utopia\Storage\Validator\FileExt; use Utopia\Storage\Validator\FileSize; use Utopia\Storage\Validator\Upload; -use Appwrite\Utopia\Response; use Utopia\Swoole\Request; -use Appwrite\Task\Validator\Cron; -use Appwrite\Utopia\Database\Validator\Queries\Deployments; -use Appwrite\Utopia\Database\Validator\Queries\Executions; -use Appwrite\Utopia\Database\Validator\Queries\Functions; -use Utopia\App; -use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\DateTime; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Validator\ArrayList; -use Utopia\Validator\Text; -use Utopia\Validator\Range; -use Utopia\Validator\WhiteList; -use Utopia\Config\Config; -use Executor\Executor; -use Utopia\CLI\Console; -use Utopia\Database\Validator\Roles; use Utopia\Validator\Boolean; -use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Validator\Range; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; -include_once __DIR__ . '/../shared/api.php'; +include_once __DIR__.'/../shared/api.php'; App::post('/v1/functions') ->groups(['api', 'functions']) @@ -60,9 +60,9 @@ App::post('/v1/functions') ->label('sdk.response.model', Response::MODEL_FUNCTION) ->param('functionId', '', new CustomId(), 'Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) + ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 64 characters long.', true) ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.') - ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) + ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.', true) ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.', true) ->param('enabled', true, new Boolean(), 'Is function enabled?', true) @@ -73,7 +73,6 @@ App::post('/v1/functions') ->inject('events') ->inject('dbForConsole') ->action(function (string $functionId, string $name, array $execute, string $runtime, array $events, string $schedule, int $timeout, bool $enabled, Response $response, Database $dbForProject, Document $project, Document $user, Event $eventsInstance, Database $dbForConsole) { - $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; $function = $dbForProject->createDocument('functions', new Document([ '$id' => $functionId, @@ -87,18 +86,18 @@ App::post('/v1/functions') 'schedule' => $schedule, 'scheduleInternalId' => '', 'timeout' => $timeout, - 'search' => implode(' ', [$functionId, $name, $runtime]) + 'search' => implode(' ', [$functionId, $name, $runtime]), ])); $schedule = Authorization::skip( - fn() => $dbForConsole->createDocument('schedules', new Document([ + fn () => $dbForConsole->createDocument('schedules', new Document([ 'region' => App::getEnv('_APP_REGION', 'default'), // Todo replace with projects region 'resourceType' => 'function', 'resourceId' => $function->getId(), 'resourceInternalId' => $function->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), - 'schedule' => $function->getAttribute('schedule'), + 'schedule' => $function->getAttribute('schedule'), 'active' => false, ])) ); @@ -125,15 +124,14 @@ App::get('/v1/functions') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_FUNCTION_LIST) - ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -173,17 +171,17 @@ App::get('/v1/functions/runtimes') ->label('sdk.response.model', Response::MODEL_RUNTIME_LIST) ->inject('response') ->action(function (Response $response) { - $runtimes = Config::getParam('runtimes'); $runtimes = array_map(function ($key) use ($runtimes) { $runtimes[$key]['$id'] = $key; + return $runtimes[$key]; }, array_keys($runtimes)); $response->dynamic(new Document([ 'total' => count($runtimes), - 'runtimes' => $runtimes + 'runtimes' => $runtimes, ]), Response::MODEL_RUNTIME_LIST); }); @@ -226,7 +224,6 @@ App::get('/v1/functions/:functionId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $functionId, string $range, Response $response, Database $dbForProject) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -270,18 +267,18 @@ App::get('/v1/functions/:functionId/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } $response->dynamic(new Document([ 'range' => $range, @@ -309,7 +306,6 @@ App::get('/v1/functions/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { - $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -348,18 +344,18 @@ App::get('/v1/functions/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } $response->dynamic(new Document([ 'range' => $range, 'functionsTotal' => $usage[$metrics[0]], @@ -389,8 +385,8 @@ App::put('/v1/functions/:functionId') ->label('sdk.response.model', Response::MODEL_FUNCTION) ->param('functionId', '', new UID(), 'Function ID.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) - ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) + ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 64 characters long.', true) + ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.', true) ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Maximum execution time in seconds.', true) ->param('enabled', true, new Boolean(), 'Is function enabled?', true) @@ -401,7 +397,6 @@ App::put('/v1/functions/:functionId') ->inject('events') ->inject('dbForConsole') ->action(function (string $functionId, string $name, array $execute, array $events, string $schedule, int $timeout, bool $enabled, Response $response, Database $dbForProject, Document $project, Document $user, Event $eventsInstance, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -424,7 +419,7 @@ App::put('/v1/functions/:functionId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $eventsInstance->setParam('functionId', $function->getId()); @@ -454,7 +449,6 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') ->inject('events') ->inject('dbForConsole') ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $events, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); @@ -484,7 +478,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $events @@ -515,14 +509,13 @@ App::delete('/v1/functions/:functionId') ->inject('project') ->inject('dbForConsole') ->action(function (string $functionId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Document $project, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('functions', $function->getId())) { + if (! $dbForProject->deleteDocument('functions', $function->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove function from DB'); } @@ -570,7 +563,6 @@ App::post('/v1/functions/:functionId/deployments') ->inject('deviceLocal') ->inject('dbForConsole') ->action(function (string $functionId, string $entrypoint, mixed $code, bool $activate, Request $request, Response $response, Database $dbForProject, Event $events, Document $project, Device $deviceFunctions, Device $deviceLocal, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -597,7 +589,7 @@ App::post('/v1/functions/:functionId/deployments') $fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name']; $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; - if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed + if (! $fileExt->isValid($file['name'])) { // Check if file type is allowed throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED); } @@ -606,7 +598,7 @@ App::post('/v1/functions/:functionId/deployments') $chunk = 1; $chunks = 1; - if (!empty($contentRange)) { + if (! empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); @@ -627,21 +619,21 @@ App::post('/v1/functions/:functionId/deployments') } } - if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit + if (! $fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); } - if (!$upload->isValid($fileTmpName)) { + if (! $upload->isValid($fileTmpName)) { throw new Exception(Exception::STORAGE_INVALID_FILE); } // Save to storage $fileSize ??= $deviceLocal->getFileSize($fileTmpName); - $path = $deviceFunctions->getPath($deploymentId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); + $path = $deviceFunctions->getPath($deploymentId.'.'.\pathinfo($fileName, PATHINFO_EXTENSION)); $deployment = $dbForProject->getDocument('deployments', $deploymentId); $metadata = ['content_type' => $deviceLocal->getFileMimeType($fileTmpName)]; - if (!$deployment->isEmpty()) { + if (! $deployment->isEmpty()) { $chunks = $deployment->getAttribute('chunksTotal', 1); $metadata = $deployment->getAttribute('metadata', []); if ($chunk === -1) { @@ -663,7 +655,7 @@ App::post('/v1/functions/:functionId/deployments') $activeDeployments = $dbForProject->find('deployments', [ Query::equal('activate', [true]), Query::equal('resourceId', [$functionId]), - Query::equal('resourceType', ['functions']) + Query::equal('resourceType', ['functions']), ]); foreach ($activeDeployments as $activeDeployment) { @@ -755,12 +747,11 @@ App::get('/v1/functions/:functionId/deployments') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST) ->param('functionId', '', new UID(), 'Function ID.') - ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -769,7 +760,7 @@ App::get('/v1/functions/:functionId/deployments') $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -827,7 +818,6 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId') ->inject('response') ->inject('dbForProject') ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -873,7 +863,6 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') ->inject('events') ->inject('deviceFunctions') ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Device $deviceFunctions) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -889,7 +878,7 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') } if ($deviceFunctions->delete($deployment->getAttribute('path', ''))) { - if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) { + if (! $dbForProject->deleteDocument('deployments', $deployment->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); } } @@ -933,7 +922,6 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') ->inject('project') ->inject('events') ->action(function (string $functionId, string $deploymentId, string $buildId, Response $response, Database $dbForProject, Document $project, Event $events) { - $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -998,11 +986,10 @@ App::post('/v1/functions/:functionId/executions') ->inject('queueForFunctions') ->inject('queueForUsage') ->action(function (string $functionId, string $data, bool $async, Response $response, Document $project, Database $dbForProject, Document $user, Event $events, string $mode, Func $queueForFunctions, Usage $queueForUsage) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - if ($function->isEmpty() || !$function->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($function->isEmpty() || ! $function->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } } @@ -1012,7 +999,7 @@ App::post('/v1/functions/:functionId/executions') $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; if (\is_null($runtime)) { - throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); } $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); @@ -1037,7 +1024,7 @@ App::post('/v1/functions/:functionId/executions') $validator = new Authorization('execute'); - if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function + if (! $validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } @@ -1046,7 +1033,7 @@ App::post('/v1/functions/:functionId/executions') /** @var Document $execution */ $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', new Document([ '$id' => $executionId, - '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], + '$permissions' => ! $user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], 'functionInternalId' => $function->getInternalId(), 'functionId' => $function->getId(), 'deploymentInternalId' => $deployment->getInternalId(), @@ -1061,7 +1048,7 @@ App::post('/v1/functions/:functionId/executions') ]))); $jwt = ''; // initialize - if (!$user->isEmpty()) { // If userId exists, generate a JWT for function + if (! $user->isEmpty()) { // If userId exists, generate a JWT for function $sessions = $user->getAttribute('sessions', []); $current = new Document(); @@ -1072,7 +1059,7 @@ App::post('/v1/functions/:functionId/executions') } } - if (!$current->isEmpty()) { + if (! $current->isEmpty()) { $jwtObj = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway. $jwt = $jwtObj->encode([ 'userId' => $user->getId(), @@ -1104,6 +1091,7 @@ App::post('/v1/functions/:functionId/executions') $vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) { $carry[$var->getAttribute('key')] = $var->getAttribute('value') ?? ''; + return $carry; }, []); @@ -1145,13 +1133,13 @@ App::post('/v1/functions/:functionId/executions') * Sync execution compute usage from */ $queueForUsage - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($executionResponse['duration'] * 1000))// per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($executionResponse['duration'] * 1000))// per function - ; + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int) ($executionResponse['duration'] * 1000))// per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int) ($executionResponse['duration'] * 1000))// per function +; } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); $execution - ->setAttribute('duration', (float)$interval->format('%s.%f')) + ->setAttribute('duration', (float) $interval->format('%s.%f')) ->setAttribute('status', 'failed') ->setAttribute('statusCode', $th->getCode()) ->setAttribute('stderr', $th->getMessage()); @@ -1164,7 +1152,7 @@ App::post('/v1/functions/:functionId/executions') $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); - if (!$isPrivilegedUser && !$isAppUser) { + if (! $isPrivilegedUser && ! $isAppUser) { $execution->setAttribute('stdout', ''); $execution->setAttribute('stderr', ''); } @@ -1186,24 +1174,23 @@ App::get('/v1/functions/:functionId/executions') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_EXECUTION_LIST) ->param('functionId', '', new UID(), 'Function ID.') - ->param('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('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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - if ($function->isEmpty() || !$function->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($function->isEmpty() || ! $function->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } } $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -1233,10 +1220,11 @@ App::get('/v1/functions/:functionId/executions') $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); - if (!$isPrivilegedUser && !$isAppUser) { + if (! $isPrivilegedUser && ! $isAppUser) { $results = array_map(function ($execution) { $execution->setAttribute('stdout', ''); $execution->setAttribute('stderr', ''); + return $execution; }, $results); } @@ -1264,11 +1252,10 @@ App::get('/v1/functions/:functionId/executions/:executionId') ->inject('dbForProject') ->inject('mode') ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, string $mode) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - if ($function->isEmpty() || !$function->getAttribute('enabled')) { - if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($function->isEmpty() || ! $function->getAttribute('enabled')) { + if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } } @@ -1286,7 +1273,7 @@ App::get('/v1/functions/:functionId/executions/:executionId') $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); - if (!$isPrivilegedUser && !$isAppUser) { + if (! $isPrivilegedUser && ! $isAppUser) { $execution->setAttribute('stdout', ''); $execution->setAttribute('stderr', ''); } @@ -1310,7 +1297,7 @@ App::post('/v1/functions/:functionId/variables') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_VARIABLE) ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) + ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: '.Database::LENGTH_KEY.' chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) ->inject('response') ->inject('dbForProject') @@ -1348,7 +1335,7 @@ App::post('/v1/functions/:functionId/variables') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $dbForProject->deleteCachedDocument('functions', $function->getId()); @@ -1357,7 +1344,7 @@ App::post('/v1/functions/:functionId/variables') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $response @@ -1447,7 +1434,6 @@ App::put('/v1/functions/:functionId/variables/:variableId') ->inject('dbForProject') ->inject('dbForConsole') ->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -1466,8 +1452,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') $variable ->setAttribute('key', $key) ->setAttribute('value', $value ?? $variable->getAttribute('value')) - ->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key])) - ; + ->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key])); try { $dbForProject->updateDocument('variables', $variable->getId(), $variable); @@ -1479,7 +1464,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $dbForProject->deleteCachedDocument('functions', $function->getId()); @@ -1488,7 +1473,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); @@ -1533,7 +1518,7 @@ App::delete('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $dbForProject->deleteCachedDocument('functions', $function->getId()); @@ -1542,7 +1527,7 @@ App::delete('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index 8ee3b5ac47..b4eb5ef620 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -42,11 +42,11 @@ App::get('/v1/graphql') 'query' => $query, ]; - if (!empty($operationName)) { + if (! empty($operationName)) { $query['operationName'] = $operationName; } - if (!empty($variables)) { + if (! empty($variables)) { $query['variables'] = \json_decode($variables, true); } @@ -150,10 +150,11 @@ App::post('/v1/graphql') /** * Execute a GraphQL request * - * @param GQLSchema $schema - * @param Adapter $promiseAdapter - * @param array $query + * @param GQLSchema $schema + * @param Adapter $promiseAdapter + * @param array $query * @return array + * * @throws Exception */ function execute( @@ -165,7 +166,7 @@ function execute( $maxComplexity = App::getEnv('_APP_GRAPHQL_MAX_COMPLEXITY', 250); $maxDepth = App::getEnv('_APP_GRAPHQL_MAX_DEPTH', 3); - if (!empty($query) && !isset($query[0])) { + if (! empty($query) && ! isset($query[0])) { $query = [$query]; } if (empty($query)) { @@ -224,7 +225,7 @@ function execute( /** * Parse an "application/graphql" type request * - * @param Request $request + * @param Request $request * @return array */ function parseGraphql(Request $request): array @@ -235,8 +236,8 @@ function parseGraphql(Request $request): array /** * Parse an "multipart/form-data" type request * - * @param array $query - * @param Request $request + * @param array $query + * @param Request $request * @return array */ function parseMultipart(array $query, Request $request): array @@ -248,7 +249,7 @@ function parseMultipart(array $query, Request $request): array foreach ($locations as $location) { $items = &$operations; foreach (\explode('.', $location) as $key) { - if (!isset($items[$key]) || !\is_array($items[$key])) { + if (! isset($items[$key]) || ! \is_array($items[$key])) { $items[$key] = []; } $items = &$items[$key]; @@ -276,7 +277,7 @@ function parseMultipart(array $query, Request $request): array function processResult($result, $debugFlags): array { // Only one query, return the result - if (!isset($result[1])) { + if (! isset($result[1])) { return $result[0]->toArray($debugFlags); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index d6a2612f32..4cac066cc6 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -28,11 +28,10 @@ App::get('/v1/health') ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) ->inject('response') ->action(function (Response $response) { - $output = [ 'name' => 'http', 'status' => 'pass', - 'ping' => 0 + 'ping' => 0, ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -47,7 +46,7 @@ App::get('/v1/health/version') ->label('sdk.response.model', Response::MODEL_HEALTH_VERSION) ->inject('response') ->action(function (Response $response) { - $response->dynamic(new Document([ 'version' => APP_VERSION_STABLE ]), Response::MODEL_HEALTH_VERSION); + $response->dynamic(new Document(['version' => APP_VERSION_STABLE]), Response::MODEL_HEALTH_VERSION); }); App::get('/v1/health/db') @@ -64,7 +63,6 @@ App::get('/v1/health/db') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; $configs = [ @@ -81,22 +79,22 @@ App::get('/v1/health/db') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } else { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } @@ -122,7 +120,6 @@ App::get('/v1/health/cache') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; $configs = [ @@ -138,22 +135,22 @@ App::get('/v1/health/cache') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } else { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } @@ -179,7 +176,6 @@ App::get('/v1/health/queue') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; $configs = [ @@ -195,22 +191,22 @@ App::get('/v1/health/queue') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } else { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } @@ -236,7 +232,6 @@ App::get('/v1/health/pubsub') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; $configs = [ @@ -252,22 +247,22 @@ App::get('/v1/health/pubsub') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } else { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key." ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]); } } @@ -292,7 +287,6 @@ App::get('/v1/health/time') ->label('sdk.response.model', Response::MODEL_HEALTH_TIME) ->inject('response') ->action(function (Response $response) { - /* * Code from: @see https://www.beliefmedia.com.au/query-ntp-time-server */ @@ -305,7 +299,7 @@ App::get('/v1/health/time') \socket_connect($sock, $host, 123); /* Send request */ - $msg = "\010" . \str_repeat("\0", 47); + $msg = "\010".\str_repeat("\0", 47); \socket_send($sock, $msg, \strlen($msg), 0); @@ -330,7 +324,7 @@ App::get('/v1/health/time') $output = [ 'remoteTime' => $timestamp, 'localTime' => \time(), - 'diff' => $diff + 'diff' => $diff, ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_TIME); @@ -349,8 +343,7 @@ App::get('/v1/health/queue/webhooks') ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->action(function (Response $response) { - - $response->dynamic(new Document([ 'size' => Resque::size(Event::WEBHOOK_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE); + $response->dynamic(new Document(['size' => Resque::size(Event::WEBHOOK_QUEUE_NAME)]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/queue/logs') @@ -366,8 +359,7 @@ App::get('/v1/health/queue/logs') ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->action(function (Response $response) { - - $response->dynamic(new Document([ 'size' => Resque::size(Event::AUDITS_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE); + $response->dynamic(new Document(['size' => Resque::size(Event::AUDITS_QUEUE_NAME)]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/queue/certificates') @@ -383,8 +375,7 @@ App::get('/v1/health/queue/certificates') ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->action(function (Response $response) { - - $response->dynamic(new Document([ 'size' => Resque::size(Event::CERTIFICATES_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE); + $response->dynamic(new Document(['size' => Resque::size(Event::CERTIFICATES_QUEUE_NAME)]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/queue/functions') @@ -402,7 +393,7 @@ App::get('/v1/health/queue/functions') ->inject('response') ->action(function (Connection $queue, Response $response) { $client = new Client(Event::FUNCTIONS_QUEUE_NAME, $queue); - $response->dynamic(new Document([ 'size' => $client->sumProcessingJobs() ]), Response::MODEL_HEALTH_QUEUE); + $response->dynamic(new Document(['size' => $client->sumProcessingJobs()]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/storage/local') @@ -418,31 +409,30 @@ App::get('/v1/health/storage/local') ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) ->inject('response') ->action(function (Response $response) { - $checkStart = \microtime(true); foreach ( [ - 'Uploads' => APP_STORAGE_UPLOADS, - 'Cache' => APP_STORAGE_CACHE, - 'Config' => APP_STORAGE_CONFIG, - 'Certs' => APP_STORAGE_CERTIFICATES + 'Uploads' => APP_STORAGE_UPLOADS, + 'Cache' => APP_STORAGE_CACHE, + 'Config' => APP_STORAGE_CONFIG, + 'Certs' => APP_STORAGE_CERTIFICATES, ] as $key => $volume ) { $device = new Local($volume); - if (!\is_readable($device->getRoot())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device ' . $key . ' dir is not readable'); + if (! \is_readable($device->getRoot())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device '.$key.' dir is not readable'); } - if (!\is_writable($device->getRoot())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device ' . $key . ' dir is not writable'); + if (! \is_writable($device->getRoot())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device '.$key.' dir is not writable'); } } $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000), ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -461,10 +451,9 @@ App::get('/v1/health/anti-virus') ->label('sdk.response.model', Response::MODEL_HEALTH_ANTIVIRUS) ->inject('response') ->action(function (Response $response) { - $output = [ 'status' => '', - 'version' => '' + 'version' => '', ]; if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'disabled') { // Check if scans are enabled @@ -499,7 +488,6 @@ App::get('/v1/health/stats') // Currently only used internally ->inject('register') ->inject('deviceFiles') ->action(function (Response $response, Registry $register, Device $deviceFiles) { - $cache = $register->get('cache'); $cacheStats = $cache->info(); @@ -507,7 +495,7 @@ App::get('/v1/health/stats') // Currently only used internally $response ->json([ 'storage' => [ - 'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot() . '/')), + 'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot().'/')), 'partitionTotal' => Storage::human($deviceFiles->getPartitionTotalSpace()), 'partitionFree' => Storage::human($deviceFiles->getPartitionFreeSpace()), ], diff --git a/app/controllers/api/locale.php b/app/controllers/api/locale.php index 29b4932543..5fd423349a 100644 --- a/app/controllers/api/locale.php +++ b/app/controllers/api/locale.php @@ -1,7 +1,7 @@ getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - $output['continent'] = $locale->getText('continents.' . strtolower($record['continent']['code']), $locale->getText('locale.country.unknown')); + $output['country'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output['continent'] = $locale->getText('continents.'.strtolower($record['continent']['code']), $locale->getText('locale.country.unknown')); $output['continentCode'] = $record['continent']['code']; $output['eu'] = (\in_array($record['country']['iso_code'], $eu)) ? true : false; @@ -62,9 +62,9 @@ App::get('/v1/locale') } $response - ->addHeader('Cache-Control', 'public, max-age=' . $time) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache - ; + ->addHeader('Cache-Control', 'public, max-age='.$time) + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache +; $response->dynamic(new Document($output), Response::MODEL_LOCALE); }); @@ -111,7 +111,7 @@ App::get('/v1/locale/countries') foreach ($list as $value) { $output[] = new Document([ - 'name' => $locale->getText('countries.' . strtolower($value)), + 'name' => $locale->getText('countries.'.strtolower($value)), 'code' => $value, ]); } @@ -143,9 +143,9 @@ App::get('/v1/locale/countries/eu') $output = []; foreach ($eu as $code) { - if ($locale->getText('countries.' . strtolower($code), false) !== false) { + if ($locale->getText('countries.'.strtolower($code), false) !== false) { $output[] = new Document([ - 'name' => $locale->getText('countries.' . strtolower($code)), + 'name' => $locale->getText('countries.'.strtolower($code)), 'code' => $code, ]); } @@ -180,11 +180,11 @@ App::get('/v1/locale/countries/phones') \asort($list); foreach ($list as $code => $name) { - if ($locale->getText('countries.' . strtolower($code), false) !== false) { + if ($locale->getText('countries.'.strtolower($code), false) !== false) { $output[] = new Document([ - 'code' => '+' . $list[$code], + 'code' => '+'.$list[$code], 'countryCode' => $code, - 'countryName' => $locale->getText('countries.' . strtolower($code)), + 'countryName' => $locale->getText('countries.'.strtolower($code)), ]); } } @@ -212,7 +212,7 @@ App::get('/v1/locale/continents') foreach ($list as $value) { $output[] = new Document([ - 'name' => $locale->getText('continents.' . strtolower($value)), + 'name' => $locale->getText('continents.'.strtolower($value)), 'code' => $value, ]); } @@ -246,7 +246,6 @@ App::get('/v1/locale/currencies') $response->dynamic(new Document(['currencies' => $list, 'total' => \count($list)]), Response::MODEL_CURRENCY_LIST); }); - App::get('/v1/locale/languages') ->desc('List Languages') ->groups(['api', 'locale']) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1ff95fbeea..a2d7cc6419 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -25,35 +25,35 @@ App::get('/v1/messaging/providers') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) - ->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('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) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, Database $dbForProject, Response $response) { - $queries = Query::parseQueries($queries); + $queries = Query::parseQueries($queries); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); - $cursor = reset($cursor); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); - if ($cursor) { - $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ - Query::equal('$id', [$providerId]), - Query::limit(1), - ])); + if ($cursor) { + $providerId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ + Query::equal('$id', [$providerId]), + Query::limit(1), + ])); - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); - } + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); + } - $cursor->setValue($cursorDocument[0]); - } + $cursor->setValue($cursorDocument[0]); + } - $filterQueries = Query::groupByType($queries)['filters']; - $response->dynamic(new Document([ - 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), - 'indexes' => $dbForProject->find('providers', $queries), - ]), Response::MODEL_PROVIDER_LIST); + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), + 'indexes' => $dbForProject->find('providers', $queries), + ]), Response::MODEL_PROVIDER_LIST); }); App::get('/v1/messaging/providers/:id') @@ -71,13 +71,13 @@ App::get('/v1/messaging/providers/:id') ->inject('dbForProject') ->inject('response') ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $response->dynamic($provider, Response::MODEL_PROVIDER); + $response->dynamic($provider, Response::MODEL_PROVIDER); }); /** @@ -101,18 +101,18 @@ App::post('/v1/messaging/providers/mailgun') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'mailgun', - 'type' => 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - 'domain' => $domain, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'mailgun', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + 'domain' => $domain, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/mailgun') @@ -134,39 +134,39 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'mailgun') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'mailgun') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey || $domain) { - // Check if all five variables are present - if ($apiKey && $domain) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'domain' => $domain - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($apiKey || $domain) { + // Check if all five variables are present + if ($apiKey && $domain) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'domain' => $domain, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/sendgrid') @@ -186,17 +186,17 @@ App::post('/v1/messaging/providers/sendgrid') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'sendgrid', - 'type' => 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'sendgrid', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/sendgrid') @@ -217,32 +217,32 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'sendgrid') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'sendgrid') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey - ]); - } + if ($apiKey) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + ]); + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); /** @@ -266,18 +266,18 @@ App::post('/v1/messaging/providers/msg91') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'msg91', - 'type' => 'sms', - 'credentials' => [ - 'senderId' => $senderId, - 'authKey' => $authKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'msg91', + 'type' => 'sms', + 'credentials' => [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/msg91') @@ -299,39 +299,39 @@ App::patch('/v1/messaging/providers/:id/msg91') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'msg91') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'msg91') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($senderId || $authKey) { - // Check if all five variables are present - if ($senderId && $authKey) { - $provider->setAttribute('credentials', [ - 'senderId' => $senderId, - 'authKey' => $authKey - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($senderId || $authKey) { + // Check if all five variables are present + if ($senderId && $authKey) { + $provider->setAttribute('credentials', [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/telesign') @@ -352,18 +352,18 @@ App::post('/v1/messaging/providers/telesign') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'telesign', - 'type' => 'sms', - 'credentials' => [ - 'username' => $username, - 'password' => $password, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'telesign', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'password' => $password, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/telesign') @@ -385,39 +385,39 @@ App::patch('/v1/messaging/providers/:id/telesign') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'telesign') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'telesign') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($username || $password) { - // Check if all five variables are present - if ($username && $password) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'password' => $password - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($username || $password) { + // Check if all five variables are present + if ($username && $password) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'password' => $password, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/textmagic') @@ -438,18 +438,18 @@ App::post('/v1/messaging/providers/textmagic') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'text-magic', - 'type' => 'sms', - 'credentials' => [ - 'username' => $username, - 'apiKey' => $apiKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'text-magic', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/textmagic') @@ -471,39 +471,39 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'text-magic') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'text-magic') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($username || $apiKey) { - // Check if all five variables are present - if ($username && $apiKey) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'apiKey' => $apiKey - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($username || $apiKey) { + // Check if all five variables are present + if ($username && $apiKey) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'apiKey' => $apiKey, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/twilio') @@ -524,18 +524,18 @@ App::post('/v1/messaging/providers/twilio') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'twilio', - 'type' => 'sms', - 'credentials' => [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'twilio', + 'type' => 'sms', + 'credentials' => [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/twilio') @@ -557,39 +557,39 @@ App::patch('/v1/messaging/providers/:id/twilio') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'twilio') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'twilio') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($accountSid || $authToken) { - // Check if all five variables are present - if ($accountSid && $authToken) { - $provider->setAttribute('credentials', [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($accountSid || $authToken) { + // Check if all five variables are present + if ($accountSid && $authToken) { + $provider->setAttribute('credentials', [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/vonage') @@ -610,18 +610,18 @@ App::post('/v1/messaging/providers/vonage') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'vonage', - 'type' => 'sms', - 'credentials' => [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'vonage', + 'type' => 'sms', + 'credentials' => [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/vonage') @@ -643,39 +643,39 @@ App::patch('/v1/messaging/providers/:id/vonage') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'vonage') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'vonage') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey || $apiSecret) { - // Check if all five variables are present - if ($apiKey && $apiSecret) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($apiKey || $apiSecret) { + // Check if all five variables are present + if ($apiKey && $apiSecret) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); /** @@ -698,17 +698,17 @@ App::post('/v1/messaging/providers/fcm') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'fcm', - 'type' => 'push', - 'credentials' => [ - 'serverKey' => $serverKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'fcm', + 'type' => 'push', + 'credentials' => [ + 'serverKey' => $serverKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/fcm') @@ -729,30 +729,30 @@ App::patch('/v1/messaging/providers/:id/fcm') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'fcm') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'fcm') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($serverKey) { - $provider->setAttribute('credentials', ['serverKey' => $serverKey]); - } + if ($serverKey) { + $provider->setAttribute('credentials', ['serverKey' => $serverKey]); + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/apns') @@ -776,21 +776,21 @@ App::post('/v1/messaging/providers/apns') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'apns', - 'type' => 'push', - 'credentials' => [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'apns', + 'type' => 'push', + 'credentials' => [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/apns') @@ -815,42 +815,42 @@ App::patch('/v1/messaging/providers/:id/apns') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'apns') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'apns') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { - // Check if all five variables are present - if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { - $provider->setAttribute('credentials', [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { + // Check if all five variables are present + if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { + $provider->setAttribute('credentials', [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::delete('/v1/messaging/providers/:id') @@ -869,16 +869,16 @@ App::delete('/v1/messaging/providers/:id') ->inject('dbForProject') ->inject('response') ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $dbForProject->deleteDocument('providers', $provider->getId()); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $dbForProject->deleteDocument('providers', $provider->getId()); - $response->noContent(); + $response->noContent(); }); App::post('/v1/messaging/messages/email') @@ -904,30 +904,30 @@ App::post('/v1/messaging/messages/email') ->inject('events') ->inject('response') ->action(function (string $providerId, string $to, string $subject, string $content, string $from, string $html, DateTime $deliveryTime, Database $dbForProject, Event $eventsInstance, Response $response) { - $provider = $dbForProject->getDocument('providers', $providerId); + $provider = $dbForProject->getDocument('providers', $providerId); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $message = $dbForProject->createDocument('messages', new Document([ - 'providerId' => $provider->getId(), - 'providerInternalId' => $provider->getInternalId(), - 'to' => $to, - 'data' => [ - 'subject' => $subject, - 'content' => $content, - ], - 'deliveryTime' => $deliveryTime, - 'deliveryError' => null, - 'deliveredTo' => null, - 'delivered' => false, - 'search' => null, - ])); + $message = $dbForProject->createDocument('messages', new Document([ + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'to' => $to, + 'data' => [ + 'subject' => $subject, + 'content' => $content, + ], + 'deliveryTime' => $deliveryTime, + 'deliveryError' => null, + 'deliveredTo' => null, + 'delivered' => false, + 'search' => null, + ])); - $eventsInstance->setParam('messageId', $message->getId()); + $eventsInstance->setParam('messageId', $message->getId()); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_MESSAGE); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_MESSAGE); }); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 8d961a0450..23ebc29362 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -28,7 +28,7 @@ use Utopia\Validator\Text; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; -include_once __DIR__ . '/../shared/api.php'; +include_once __DIR__.'/../shared/api.php'; App::post('/v1/migrations/appwrite') ->groups(['api', 'migrations']) @@ -110,7 +110,7 @@ App::post('/v1/migrations/firebase/oauth') $firebase = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' + $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' ); $identity = $dbForConsole->findOne('identities', [ @@ -141,7 +141,7 @@ App::post('/v1/migrations/firebase/oauth') $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry(''))); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } @@ -167,7 +167,7 @@ App::post('/v1/migrations/firebase/oauth') 'resources' => $resources, 'statusCounters' => '{}', 'resourceData' => '{}', - 'errors' => [] + 'errors' => [], ])); $events->setParam('migrationId', $migration->getId()); @@ -368,14 +368,14 @@ App::get('/v1/migrations') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MIGRATION_LIST) - ->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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -505,7 +505,7 @@ App::get('/v1/migrations/firebase/report/oauth') $firebase = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' + $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' ); $identity = $dbForConsole->findOne('identities', [ @@ -536,7 +536,7 @@ App::get('/v1/migrations/firebase/report/oauth') $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry(''))); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } @@ -597,7 +597,7 @@ App::get('/v1/migrations/firebase/connect') $oauth2 = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' + $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' ); $url = $oauth2->getLoginURL(); @@ -611,7 +611,7 @@ App::get('/v1/migrations/firebase/redirect') ->desc('Capture and receive data on Firebase authorization') ->groups(['api', 'migrations']) ->label('scope', 'public') - ->label('error', __DIR__ . '/../../views/general/error.phtml') + ->label('error', __DIR__.'/../../views/general/error.phtml') ->param('code', '', new Text(2048), 'OAuth2 code.', true) ->inject('user') ->inject('project') @@ -635,7 +635,7 @@ App::get('/v1/migrations/firebase/redirect') $project = $dbForConsole->getDocument('projects', $projectId); if (empty($redirect)) { - $redirect = $request->getProtocol() . '://' . $request->getHostname() . '/console/project-$projectId/settings/migrations'; + $redirect = $request->getProtocol().'://'.$request->getHostname().'/console/project-$projectId/settings/migrations'; } if ($project->isEmpty()) { @@ -648,11 +648,11 @@ App::get('/v1/migrations/firebase/redirect') } // OAuth Authroization - if (!empty($code)) { + if (! empty($code)) { $oauth2 = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' + $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' ); $accessToken = $oauth2->getAccessToken($code); @@ -678,17 +678,17 @@ App::get('/v1/migrations/firebase/redirect') Query::equal('providerEmail', [$email]), ]); - if ($identity !== false && !$identity->isEmpty()) { + if ($identity !== false && ! $identity->isEmpty()) { if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } } - if ($identity !== false && !$identity->isEmpty()) { + if ($identity !== false && ! $identity->isEmpty()) { $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry)); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } else { @@ -706,7 +706,7 @@ App::get('/v1/migrations/firebase/redirect') 'providerEmail' => $email, 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), + 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry), ])); } } else { @@ -738,7 +738,7 @@ App::get('/v1/migrations/firebase/projects') $firebase = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' + $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' ); $identity = $dbForConsole->findOne('identities', [ @@ -781,7 +781,7 @@ App::get('/v1/migrations/firebase/projects') $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry(''))); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } @@ -964,7 +964,7 @@ App::delete('/v1/migrations/:migrationId') throw new Exception(Exception::MIGRATION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('migrations', $migration->getId())) { + if (! $dbForProject->deleteDocument('migrations', $migration->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove migration from DB', 500); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 0f05c6f497..0146f1c19f 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -4,7 +4,6 @@ use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -24,7 +23,6 @@ App::get('/v1/project/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { - $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -37,7 +35,7 @@ App::get('/v1/project/usage') METRIC_DATABASES, METRIC_USERS, METRIC_BUCKETS, - METRIC_FILES_STORAGE + METRIC_FILES_STORAGE, ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -60,25 +58,23 @@ App::get('/v1/project/usage') } }); - $format = match ($days['period']) { '1h' => 'Y-m-d\TH:00:00.000P', '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } - $response->dynamic(new Document([ 'range' => $range, diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 6fff6b324b..f28f5197cb 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1,19 +1,22 @@ groups(['projects']) @@ -64,7 +63,7 @@ App::post('/v1/projects') ->param('projectId', '', new ProjectId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('teamId', '', new UID(), 'Team unique ID.') - ->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn($config) => !$config['disabled']))), 'Project Region.', true) + ->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn ($config) => ! $config['disabled']))), 'Project Region.', true) ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) ->param('logo', '', new Text(1024), 'Project logo.', true) ->param('url', '', new URL(), 'Project URL.', true) @@ -79,8 +78,6 @@ App::post('/v1/projects') ->inject('cache') ->inject('pools') ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools) { - - $team = $dbForConsole->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -164,7 +161,7 @@ App::post('/v1/projects') 'domains' => null, 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), - 'database' => $database + 'database' => $database, ])); } catch (Duplicate $th) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); @@ -201,7 +198,7 @@ App::post('/v1/projects') 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' + 'format' => $attribute['format'] ?? '', ]); } @@ -232,15 +229,14 @@ App::get('/v1/projects') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT_LIST) - ->param('queries', [], new Projects(), '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('queries', [], new Projects(), '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) ->inject('response') ->inject('dbForConsole') ->action(function (array $queries, string $search, Response $response, Database $dbForConsole) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -281,7 +277,6 @@ App::get('/v1/projects/:projectId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -315,7 +310,6 @@ App::patch('/v1/projects/:projectId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -353,7 +347,6 @@ App::patch('/v1/projects/:projectId/team') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $teamId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); $team = $dbForConsole->getDocument('teams', $teamId); @@ -389,12 +382,11 @@ App::patch('/v1/projects/:projectId/service') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])), true), 'Service name.') + ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -424,14 +416,13 @@ App::patch('/v1/projects/:projectId/service/all') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $allServices = array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])); + $allServices = array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])); $services = []; foreach ($allServices as $service) { @@ -461,7 +452,6 @@ App::patch('/v1/projects/:projectId/oauth2') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -471,15 +461,15 @@ App::patch('/v1/projects/:projectId/oauth2') $providers = $project->getAttribute('authProviders', []); if ($appId !== null) { - $providers[$provider . 'Appid'] = $appId; + $providers[$provider.'Appid'] = $appId; } if ($secret !== null) { - $providers[$provider . 'Secret'] = $secret; + $providers[$provider.'Secret'] = $secret; } if ($enabled !== null) { - $providers[$provider . 'Enabled'] = $enabled; + $providers[$provider.'Enabled'] = $enabled; } $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('authProviders', $providers)); @@ -502,7 +492,6 @@ App::patch('/v1/projects/:projectId/auth/limit') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -533,7 +522,6 @@ App::patch('/v1/projects/:projectId/auth/duration') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $duration, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -560,12 +548,11 @@ App::patch('/v1/projects/:projectId/auth/:method') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false) + ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: '.implode(',', \array_keys(Config::getParam('auth'))), false) ->param('status', false, new Boolean(true), 'Set the status of this auth method.') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); $auth = Config::getParam('auth')[$method] ?? []; $authKey = $auth['key'] ?? ''; @@ -594,11 +581,10 @@ App::patch('/v1/projects/:projectId/auth/password-history') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0') + ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is'.APP_LIMIT_USER_PASSWORD_HISTORY.'. Default value is 0') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -629,7 +615,6 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -660,7 +645,6 @@ App::patch('/v1/projects/:projectId/auth/personal-data') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -687,11 +671,10 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT) + ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-'.APP_LIMIT_USER_SESSIONS_MAX.'. Default is '.APP_LIMIT_USER_SESSIONS_DEFAULT) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -730,10 +713,9 @@ App::delete('/v1/projects/:projectId') $deletes ->setType(DELETE_TYPE_DOCUMENT) - ->setDocument($project) - ; + ->setDocument($project); - if (!$dbForConsole->deleteDocument('projects', $projectId)) { + if (! $dbForConsole->deleteDocument('projects', $projectId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB'); } @@ -754,7 +736,7 @@ App::post('/v1/projects/:projectId/webhooks') ->label('sdk.response.model', Response::MODEL_WEBHOOK) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') - ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') + ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.') ->param('url', null, new URL(['http', 'https']), 'Webhook URL.') ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) @@ -762,7 +744,6 @@ App::post('/v1/projects/:projectId/webhooks') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -812,7 +793,6 @@ App::get('/v1/projects/:projectId/webhooks') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -845,7 +825,6 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -877,7 +856,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') - ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') + ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.') ->param('url', null, new URL(['http', 'https']), 'Webhook URL.') ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) @@ -885,7 +864,6 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, string $name, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -909,8 +887,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('url', $url) ->setAttribute('security', $security) ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass) - ; + ->setAttribute('httpPass', $httpPass); $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); $dbForConsole->deleteCachedDocument('projects', $project->getId()); @@ -933,7 +910,6 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -971,7 +947,6 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1008,12 +983,11 @@ App::post('/v1/projects/:projectId/keys') ->label('sdk.response.model', Response::MODEL_KEY) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') - ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') + ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' scopes are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in ISO 8601 format. Use null for unlimited expiration.', true) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1060,7 +1034,6 @@ App::get('/v1/projects/:projectId/keys') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1093,7 +1066,6 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1125,12 +1097,11 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') - ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') + ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in ISO 8601 format. Use null for unlimited expiration.', true) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1149,8 +1120,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key ->setAttribute('name', $name) ->setAttribute('scopes', $scopes) - ->setAttribute('expire', $expire) - ; + ->setAttribute('expire', $expire); $dbForConsole->updateDocument('keys', $key->getId(), $key); @@ -1173,7 +1143,6 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1236,7 +1205,7 @@ App::post('/v1/projects/:projectId/platforms') 'name' => $name, 'key' => $key, 'store' => $store, - 'hostname' => $hostname + 'hostname' => $hostname, ]); $platform = $dbForConsole->createDocument('platforms', $platform); @@ -1262,7 +1231,6 @@ App::get('/v1/projects/:projectId/platforms') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1295,7 +1263,6 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1352,8 +1319,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->setAttribute('name', $name) ->setAttribute('key', $key) ->setAttribute('store', $store) - ->setAttribute('hostname', $hostname) - ; + ->setAttribute('hostname', $hostname); $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); @@ -1376,7 +1342,6 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1416,7 +1381,6 @@ App::post('/v1/projects/:projectId/domains') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $domain, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1428,17 +1392,17 @@ App::post('/v1/projects/:projectId/domains') } $document = $dbForConsole->findOne('domains', [ - Query::equal('domain', [$domain]) + Query::equal('domain', [$domain]), ]); - if ($document && !$document->isEmpty()) { + if ($document && ! $document->isEmpty()) { throw new Exception(Exception::DOMAIN_ALREADY_EXISTS); } $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - if (!$target->isKnown() || $target->isTest()) { - throw new Exception(Exception::DOMAIN_TARGET_INVALID, 'Unreachable CNAME target (' . $target->get() . '). Please check the _APP_DOMAIN_TARGET environment variable of your Appwrite server.'); + if (! $target->isKnown() || $target->isTest()) { + throw new Exception(Exception::DOMAIN_TARGET_INVALID, 'Unreachable CNAME target ('.$target->get().'). Please check the _APP_DOMAIN_TARGET environment variable of your Appwrite server.'); } $domain = new Domain($domain); @@ -1483,7 +1447,6 @@ App::get('/v1/projects/:projectId/domains') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1516,7 +1479,6 @@ App::get('/v1/projects/:projectId/domains/:domainId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1550,7 +1512,6 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1568,8 +1529,8 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - if (!$target->isKnown() || $target->isTest()) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.'); + if (! $target->isKnown() || $target->isTest()) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unreachable CNAME target ('.$target->get().'), please use a domain with a public suffix.'); } if ($domain->getAttribute('verification') === true) { @@ -1578,11 +1539,10 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') $validator = new CNAME($target->get()); // Verify Domain with DNS records - if (!$validator->isValid($domain->getAttribute('domain', ''))) { + if (! $validator->isValid($domain->getAttribute('domain', ''))) { throw new Exception(Exception::DOMAIN_VERIFICATION_FAILED); } - $dbForConsole->updateDocument('domains', $domain->getId(), $domain->setAttribute('verification', true)); $dbForConsole->deleteCachedDocument('projects', $project->getId()); @@ -1610,7 +1570,6 @@ App::delete('/v1/projects/:projectId/domains/:domainId') ->inject('dbForConsole') ->inject('deletes') ->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole, Delete $deletes) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1663,7 +1622,6 @@ App::patch('/v1/projects/:projectId/smtp') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, string $sender, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1681,7 +1639,7 @@ App::patch('/v1/projects/:projectId/smtp') $mail->SMTPAutoTLS = false; $valid = $mail->SmtpConnect(); - if (!$valid) { + if (! $valid) { throw new Exception(Exception::GENERAL_SMTP_DISABLED); } @@ -1712,11 +1670,10 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1724,11 +1681,11 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['sms.' . $type . '-' . $locale] ?? null; + $template = $templates['sms.'.$type.'-'.$locale] ?? null; if (is_null($template)) { $template = [ - 'message' => Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl')->render(), + 'message' => Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl')->render(), ]; } @@ -1750,11 +1707,10 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1762,11 +1718,11 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['email.' . $type . '-' . $locale] ?? null; + $template = $templates['email.'.$type.'-'.$locale] ?? null; $localeObj = new Locale($locale); if (is_null($template)) { - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); + $message = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); $message = $message ->setParam('{{hello}}', $localeObj->getText("emails.{$type}.hello")) ->setParam('{{name}}', '') @@ -1781,12 +1737,12 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->render(); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($localeObj->getText('emails.sender'), $project->getAttribute('name')); - $from = empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')) : $from; + $from = empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')) : $from; $template = [ 'message' => $message, - 'subject' => $localeObj->getText('emails.' . $type . '.subject'), + 'subject' => $localeObj->getText('emails.'.$type.'.subject'), 'senderEmail' => App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', ''), - 'senderName' => $from + 'senderName' => $from, ]; } @@ -1808,12 +1764,11 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('message', '', new Text(0), 'Template message') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1821,8 +1776,8 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $templates['sms.' . $type . '-' . $locale] = [ - 'message' => $message + $templates['sms.'.$type.'-'.$locale] = [ + 'message' => $message, ]; $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); @@ -1846,7 +1801,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('senderName', '', new Text(255), 'Name of the email sender') ->param('senderEmail', '', new Email(), 'Email of the sender') ->param('subject', '', new Text(255), 'Email Subject') @@ -1855,7 +1810,6 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, string $senderName, string $senderEmail, string $subject, string $message, string $replyTo, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1863,12 +1817,12 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $templates['email.' . $type . '-' . $locale] = [ + $templates['email.'.$type.'-'.$locale] = [ 'senderName' => $senderName, 'senderEmail' => $senderEmail, 'subject' => $subject, 'replyTo' => $replyTo, - 'message' => $message + 'message' => $message, ]; $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); @@ -1880,7 +1834,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') 'senderEmail' => $senderEmail, 'subject' => $subject, 'replyTo' => $replyTo, - 'message' => $message + 'message' => $message, ]), Response::MODEL_EMAIL_TEMPLATE); }); @@ -1896,11 +1850,10 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1908,20 +1861,20 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['sms.' . $type . '-' . $locale] ?? null; + $template = $templates['sms.'.$type.'-'.$locale] ?? null; if (is_null($template)) { throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION); } - unset($template['sms.' . $type . '-' . $locale]); + unset($template['sms.'.$type.'-'.$locale]); $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, 'locale' => $locale, - 'message' => $template['message'] + 'message' => $template['message'], ]), Response::MODEL_SMS_TEMPLATE); }); @@ -1937,11 +1890,10 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1949,13 +1901,13 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['email.' . $type . '-' . $locale] ?? null; + $template = $templates['email.'.$type.'-'.$locale] ?? null; if (is_null($template)) { throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION); } - unset($templates['email.' . $type . '-' . $locale]); + unset($templates['email.'.$type.'-'.$locale]); $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); @@ -1966,6 +1918,6 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') 'senderEmail' => $template['senderEmail'], 'subject' => $template['subject'], 'replyTo' => $template['replyTo'], - 'message' => $template['message'] + 'message' => $template['message'], ]), Response::MODEL_EMAIL_TEMPLATE); }); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index c34515b5e1..3206e2231f 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -4,28 +4,27 @@ use Appwrite\Auth\Auth; use Appwrite\ClamAV\Network; use Appwrite\Event\Delete; use Appwrite\Event\Event; -use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Extend\Exception; use Appwrite\OpenSSL\OpenSSL; +use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Database\Validator\Queries\Buckets; +use Appwrite\Utopia\Database\Validator\Queries\Files; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\DateTime; -use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Authorization as AuthorizationException; +use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Query; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Appwrite\Extend\Exception; -use Appwrite\Utopia\Database\Validator\Queries\Buckets; -use Appwrite\Utopia\Database\Validator\Queries\Files; use Utopia\Image\Image; use Utopia\Storage\Compression\Algorithms\GZIP; use Utopia\Storage\Compression\Algorithms\Zstd; @@ -35,14 +34,13 @@ use Utopia\Storage\Validator\File; use Utopia\Storage\Validator\FileExt; use Utopia\Storage\Validator\FileSize; use Utopia\Storage\Validator\Upload; +use Utopia\Swoole\Request; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; use Utopia\Validator\HexColor; use Utopia\Validator\Range; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -use Utopia\DSN\DSN; -use Utopia\Swoole\Request; App::post('/v1/storage/buckets') ->desc('Create bucket') @@ -63,16 +61,15 @@ App::post('/v1/storage/buckets') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true) - ->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) - ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) - ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) - ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) + ->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is '.Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0).'. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) + ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' extensions are allowed, each 64 characters long.', true) + ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of '.COMPRESSION_TYPE_NONE.', ['.COMPRESSION_TYPE_GZIP.'](https://en.wikipedia.org/wiki/Gzip), or ['.COMPRESSION_TYPE_ZSTD.'](https://en.wikipedia.org/wiki/Zstd), For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' compression is skipped even if it\'s enabled', true) + ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' encryption is skipped even if it\'s enabled', true) + ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above '.Storage::human(APP_LIMIT_ANTIVIRUS, 0).' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('events') ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) { - $bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId; // Map aggregate permissions into the multiple permissions they represent. @@ -97,7 +94,7 @@ App::post('/v1/storage/buckets') 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' + 'format' => $attribute['format'] ?? '', ]); } @@ -128,14 +125,13 @@ App::post('/v1/storage/buckets') $bucket = $dbForProject->getDocument('buckets', $bucketId); - $dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); + $dbForProject->createCollection('bucket_'.$bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); } catch (Duplicate) { throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS); } $events - ->setParam('bucketId', $bucket->getId()) - ; + ->setParam('bucketId', $bucket->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -153,15 +149,14 @@ App::get('/v1/storage/buckets') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET_LIST) - ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -203,7 +198,6 @@ App::get('/v1/storage/buckets/:bucketId') ->inject('response') ->inject('dbForProject') ->action(function (string $bucketId, Response $response, Database $dbForProject) { - $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { @@ -232,11 +226,11 @@ App::put('/v1/storage/buckets/:bucketId') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true) - ->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) - ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) - ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) - ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) + ->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is '.Storage::human((int) App::getEnv('_APP_STORAGE_LIMIT', 0), 0).'. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) + ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' extensions are allowed, each 64 characters long.', true) + ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of '.COMPRESSION_TYPE_NONE.', ['.COMPRESSION_TYPE_GZIP.'](https://en.wikipedia.org/wiki/Gzip), or ['.COMPRESSION_TYPE_ZSTD.'](https://en.wikipedia.org/wiki/Zstd), For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' compression is skipped even if it\'s enabled', true) + ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' encryption is skipped even if it\'s enabled', true) + ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above '.Storage::human(APP_LIMIT_ANTIVIRUS, 0).' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('events') @@ -271,11 +265,10 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('encryption', $encryption) ->setAttribute('compression', $compression) ->setAttribute('antivirus', $antivirus)); - $dbForProject->updateCollection('bucket_' . $bucket->getInternalId(), $permissions, $fileSecurity); + $dbForProject->updateCollection('bucket_'.$bucket->getInternalId(), $permissions, $fileSecurity); $events - ->setParam('bucketId', $bucket->getId()) - ; + ->setParam('bucketId', $bucket->getId()); $response->dynamic($bucket, Response::MODEL_BUCKET); }); @@ -305,7 +298,7 @@ App::delete('/v1/storage/buckets/:bucketId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$dbForProject->deleteDocument('buckets', $bucketId)) { + if (! $dbForProject->deleteDocument('buckets', $bucketId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove bucket from DB'); } @@ -315,8 +308,7 @@ App::delete('/v1/storage/buckets/:bucketId') $events ->setParam('bucketId', $bucket->getId()) - ->setPayload($response->output($bucket, Response::MODEL_BUCKET)) - ; + ->setPayload($response->output($bucket, Response::MODEL_BUCKET)); $response->noContent(); }); @@ -354,15 +346,14 @@ App::post('/v1/storage/buckets/:bucketId/files') ->inject('deviceFiles') ->inject('deviceLocal') ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $validator = new Authorization(Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (! $validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -378,7 +369,7 @@ App::post('/v1/storage/buckets/:bucketId/files') // Add permissions for current the user if none were provided. if (\is_null($permissions)) { $permissions = []; - if (!empty($user->getId())) { + if (! empty($user->getId())) { foreach ($allowedPermissions as $permission) { $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); } @@ -387,7 +378,7 @@ App::post('/v1/storage/buckets/:bucketId/files') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { + if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -399,8 +390,8 @@ App::post('/v1/storage/buckets/:bucketId/files') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + if (! Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); } } } @@ -411,7 +402,6 @@ App::post('/v1/storage/buckets/:bucketId/files') throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Maximum bucket file size is larger than _APP_STORAGE_LIMIT'); } - $file = $request->getFiles('file'); // GraphQL multipart spec adds files with index keys @@ -433,7 +423,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $chunk = 1; $chunks = 1; - if (!empty($contentRange)) { + if (! empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); @@ -444,7 +434,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } $idValidator = new UID(); - if (!$idValidator->isValid($request->getHeader('x-appwrite-id'))) { + if (! $idValidator->isValid($request->getHeader('x-appwrite-id'))) { throw new Exception(Exception::STORAGE_INVALID_APPWRITE_ID); } @@ -465,30 +455,30 @@ App::post('/v1/storage/buckets/:bucketId/files') // Check if file type is allowed $allowedFileExtensions = $bucket->getAttribute('allowedFileExtensions', []); $fileExt = new FileExt($allowedFileExtensions); - if (!empty($allowedFileExtensions) && !$fileExt->isValid($fileName)) { + if (! empty($allowedFileExtensions) && ! $fileExt->isValid($fileName)) { throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, 'File extension not allowed'); } // Check if file size is exceeding allowed limit $fileSizeValidator = new FileSize($maximumFileSize); - if (!$fileSizeValidator->isValid($fileSize)) { + if (! $fileSizeValidator->isValid($fileSize)) { throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE, 'File size not allowed'); } $upload = new Upload(); - if (!$upload->isValid($fileTmpName)) { + if (! $upload->isValid($fileTmpName)) { throw new Exception(Exception::STORAGE_INVALID_FILE); } // Save to storage $fileSize ??= $deviceLocal->getFileSize($fileTmpName); - $path = $deviceFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); - $path = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root + $path = $deviceFiles->getPath($fileId.'.'.\pathinfo($fileName, PATHINFO_EXTENSION)); + $path = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot().DIRECTORY_SEPARATOR.$bucket->getId(), $path); // Add bucket id to path after root - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); $metadata = ['content_type' => $deviceLocal->getFileMimeType($fileTmpName)]; - if (!$file->isEmpty()) { + if (! $file->isEmpty()) { $chunks = $file->getAttribute('chunksTotal', 1); $metadata = $file->getAttribute('metadata', []); if ($chunk === -1) { @@ -508,7 +498,7 @@ App::post('/v1/storage/buckets/:bucketId/files') (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310) ); - if (!$antivirus->fileScan($path)) { + if (! $antivirus->fileScan($path)) { $deviceFiles->delete($path); throw new Exception(Exception::STORAGE_INVALID_FILE); } @@ -542,8 +532,8 @@ App::post('/v1/storage/buckets/:bucketId/files') $data = OpenSSL::encrypt($data, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag); } - if (!empty($data)) { - if (!$deviceFiles->write($path, $data, $mimeType)) { + if (! empty($data)) { + if (! $deviceFiles->write($path, $data, $mimeType)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to save file'); } } @@ -587,7 +577,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_'.$bucket->getInternalId(), $doc); } else { $file = $file ->setAttribute('$permissions', $permissions) @@ -602,7 +592,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ->setAttribute('metadata', $metadata) ->setAttribute('chunksUploaded', $chunksUploaded); - $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file); } } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); @@ -633,13 +623,13 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_'.$bucket->getInternalId(), $doc); } else { $file = $file ->setAttribute('chunksUploaded', $chunksUploaded) ->setAttribute('metadata', $metadata); - $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file); } } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); @@ -653,8 +643,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $events ->setParam('bucketId', $bucket->getId()) ->setParam('fileId', $file->getId()) - ->setContext('bucket', $bucket) - ; + ->setContext('bucket', $bucket); $metadata = null; // was causing leaks as it was passed by reference @@ -676,29 +665,28 @@ App::get('/v1/storage/buckets/:bucketId/files') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_FILE_LIST) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).') - ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -709,10 +697,10 @@ App::get('/v1/storage/buckets/:bucketId/files') /** @var Query $cursor */ $fileId = $cursor->getValue(); - if ($fileSecurity && !$valid) { - $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + if ($fileSecurity && ! $valid) { + $cursorDocument = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); } else { - $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -724,12 +712,12 @@ App::get('/v1/storage/buckets/:bucketId/files') $filterQueries = Query::groupByType($queries)['filters']; - if ($fileSecurity && !$valid) { - $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); - $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + if ($fileSecurity && ! $valid) { + $files = $dbForProject->find('bucket_'.$bucket->getInternalId(), $queries); + $total = $dbForProject->count('bucket_'.$bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_'.$bucket->getInternalId(), $queries)); + $total = Authorization::skip(fn () => $dbForProject->count('bucket_'.$bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); } $response->dynamic(new Document([ @@ -756,24 +744,23 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('dbForProject') ->inject('mode') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + if ($fileSecurity && ! $valid) { + $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -802,7 +789,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->param('fileId', '', new UID(), 'File ID') ->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true) ->param('height', 0, new Range(0, 4000), 'Resize preview image height, Pass an integer between 0 to 4000.', true) - ->param('gravity', Image::GRAVITY_CENTER, new WhiteList(Image::getGravityTypes()), 'Image crop gravity. Can be one of ' . implode(",", Image::getGravityTypes()), true) + ->param('gravity', Image::GRAVITY_CENTER, new WhiteList(Image::getGravityTypes()), 'Image crop gravity. Can be one of '.implode(',', Image::getGravityTypes()), true) ->param('quality', 100, new Range(0, 100), 'Preview image quality. Pass an integer between 0 to 100. Defaults to 100.', true) ->param('borderWidth', 0, new Range(0, 100), 'Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.', true) ->param('borderColor', '', new HexColor(), 'Preview image border color. Use a valid HEX color, no # is needed for prefix.', true) @@ -819,21 +806,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->inject('deviceFiles') ->inject('deviceLocal') ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceFiles, Device $deviceLocal) { - - if (!\extension_loaded('imagick')) { + if (! \extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -845,10 +831,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $outputs = Config::getParam('storage-outputs'); $fileLogos = Config::getParam('storage-logos'); - if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + if ($fileSecurity && ! $valid) { + $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -860,8 +846,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $algorithm = $file->getAttribute('algorithm', 'none'); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); - if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { - if (!\in_array($mime, $inputs)) { + if (! \in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { + if (! \in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { // it was an image but the file size exceeded the limit @@ -875,7 +861,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $deviceFiles = $deviceLocal; } - if (!$deviceFiles->exists($path)) { + if (! $deviceFiles->exists($path)) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -885,14 +871,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $output = empty($type) ? (array_search($mime, $outputs) ?? 'jpg') : $type; } - $source = $deviceFiles->read($path); - if (!empty($cipher)) { // Decrypt + if (! empty($cipher)) { // Decrypt $source = OpenSSL::decrypt( $source, $file->getAttribute('openSSLCipher'), - App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')), + App::getEnv('_APP_OPENSSL_KEY_V'.$file->getAttribute('openSSLVersion')), 0, \hex2bin($file->getAttribute('openSSLIV')), \hex2bin($file->getAttribute('openSSLTag')) @@ -914,23 +899,23 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $image->crop((int) $width, (int) $height, $gravity); - if (!empty($opacity) || $opacity === 0) { + if (! empty($opacity) || $opacity === 0) { $image->setOpacity($opacity); } - if (!empty($background)) { - $image->setBackground('#' . $background); + if (! empty($background)) { + $image->setBackground('#'.$background); } - if (!empty($borderWidth)) { - $image->setBorder($borderWidth, '#' . $borderColor); + if (! empty($borderWidth)) { + $image->setBorder($borderWidth, '#'.$borderColor); } - if (!empty($borderRadius)) { + if (! empty($borderRadius)) { $image->setBorderRadius($borderRadius); } - if (!empty($rotation)) { + if (! empty($rotation)) { $image->setRotation(($rotation + 360) % 360); } @@ -939,10 +924,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') ->setContentType($contentType) - ->file($data) - ; + ->file($data); unset($image); }); @@ -967,24 +951,23 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->inject('mode') ->inject('deviceFiles') ->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceFiles) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + if ($fileSecurity && ! $valid) { + $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -993,21 +976,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $path = $file->getAttribute('path', ''); - if (!$deviceFiles->exists($path)) { - throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); + if (! $deviceFiles->exists($path)) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in '.$path); } $response ->setContentType($file->getAttribute('mimeType')) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') - ; + ->addHeader('Content-Disposition', 'attachment; filename="'.$file->getAttribute('name', '').'"'); $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); - if (!empty($rangeHeader)) { + if (! empty($rangeHeader)) { $start = $request->getRangeStart(); $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); @@ -1022,18 +1004,18 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $response ->addHeader('Accept-Ranges', 'bytes') - ->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size) + ->addHeader('Content-Range', 'bytes '.$start.'-'.$end.'/'.$size) ->addHeader('Content-Length', $end - $start + 1) ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } $source = ''; - if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt + if (! empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceFiles->read($path); $source = OpenSSL::decrypt( $source, $file->getAttribute('openSSLCipher'), - App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')), + App::getEnv('_APP_OPENSSL_KEY_V'.$file->getAttribute('openSSLVersion')), 0, \hex2bin($file->getAttribute('openSSLIV')), \hex2bin($file->getAttribute('openSSLTag')) @@ -1057,14 +1039,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') break; } - if (!empty($source)) { - if (!empty($rangeHeader)) { + if (! empty($source)) { + if (! empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); } - if (!empty($rangeHeader)) { + if (! empty($rangeHeader)) { $response->send($deviceFiles->read($path, $start, ($end - $start + 1))); } @@ -1105,24 +1087,23 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->inject('mode') ->inject('deviceFiles') ->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceFiles) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + if ($fileSecurity && ! $valid) { + $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -1133,8 +1114,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $path = $file->getAttribute('path', ''); - if (!$deviceFiles->exists($path)) { - throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); + if (! $deviceFiles->exists($path)) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in '.$path); } $contentType = 'text/plain'; @@ -1147,15 +1128,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setContentType($contentType) ->addHeader('Content-Security-Policy', 'script-src none;') ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache - ->addHeader('X-Peak', \memory_get_peak_usage()) - ; + ->addHeader('Content-Disposition', 'inline; filename="'.$file->getAttribute('name', '').'"') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('X-Peak', \memory_get_peak_usage()); $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); - if (!empty($rangeHeader)) { + if (! empty($rangeHeader)) { $start = $request->getRangeStart(); $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); @@ -1176,12 +1156,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } $source = ''; - if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt + if (! empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceFiles->read($path); $source = OpenSSL::decrypt( $source, $file->getAttribute('openSSLCipher'), - App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')), + App::getEnv('_APP_OPENSSL_KEY_V'.$file->getAttribute('openSSLVersion')), 0, \hex2bin($file->getAttribute('openSSLIV')), \hex2bin($file->getAttribute('openSSLTag')) @@ -1205,14 +1185,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') break; } - if (!empty($source)) { - if (!empty($rangeHeader)) { + if (! empty($source)) { + if (! empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); } - if (!empty($rangeHeader)) { + if (! empty($rangeHeader)) { $response->send($deviceFiles->read($path, $start, ($end - $start + 1))); } @@ -1262,22 +1242,21 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('mode') ->inject('events') ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $events) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttributes('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_UPDATE); $valid = $validator->isValid($bucket->getUpdate()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for update - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1292,7 +1271,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { + if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles) && ! \is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -1304,8 +1283,8 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + if (! Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); } } } @@ -1317,25 +1296,24 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $file->setAttribute('$permissions', $permissions); - if (!is_null($name)) { + if (! is_null($name)) { $file->setAttribute('name', $name); } - if ($fileSecurity && !$valid) { + if ($fileSecurity && ! $valid) { try { - $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } } else { - $file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file)); } $events ->setParam('bucketId', $bucket->getId()) ->setParam('fileId', $file->getId()) - ->setContext('bucket', $bucket) - ; + ->setContext('bucket', $bucket); $response->dynamic($file, Response::MODEL_FILE); }); @@ -1368,26 +1346,26 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $events, string $mode, Device $deviceFiles, Delete $deletes) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttributes('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_DELETE); $valid = $validator->isValid($bucket->getDelete()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for delete - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } // Make sure we don't delete the file before the document permission check occurs - if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) { + if ($fileSecurity && ! $valid && ! $validator->isValid($file->getDelete())) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1404,20 +1382,19 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') if ($deviceDeleted) { $deletes ->setType(DELETE_TYPE_CACHE_BY_RESOURCE) - ->setResource('file/' . $fileId) - ; + ->setResource('file/'.$fileId); - if ($fileSecurity && !$valid) { + if ($fileSecurity && ! $valid) { try { - $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); + $deleted = $dbForProject->deleteDocument('bucket_'.$bucket->getInternalId(), $fileId); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } } else { - $deleted = Authorization::skip(fn() => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_'.$bucket->getInternalId(), $fileId)); } - if (!$deleted) { + if (! $deleted) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove file from DB'); } } else { @@ -1428,8 +1405,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->setParam('bucketId', $bucket->getId()) ->setParam('fileId', $file->getId()) ->setContext('bucket', $bucket) - ->setPayload($response->output($file, Response::MODEL_FILE)) - ; + ->setPayload($response->output($file, Response::MODEL_FILE)); $response->noContent(); }); @@ -1448,7 +1424,6 @@ App::get('/v1/storage/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { - $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -1518,7 +1493,6 @@ App::get('/v1/storage/:bucketId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $bucketId, string $range, Response $response, Database $dbForProject) { - $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index e03e481d7c..e50378f4b6 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -9,14 +9,10 @@ use Appwrite\Event\Mail; use Appwrite\Event\Phone as EventPhone; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; -use Utopia\Validator\Host; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; -use Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Memberships; use Appwrite\Utopia\Database\Validator\Queries\Teams; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -24,20 +20,24 @@ use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Query; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; +use Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; +use Utopia\Validator\Host; use Utopia\Validator\Text; App::post('/v1/teams') @@ -56,20 +56,19 @@ App::post('/v1/teams') ->label('sdk.response.model', Response::MODEL_TEAM) ->param('teamId', '', new CustomId(), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') - ->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true) + ->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 32 characters long.', true) ->inject('response') ->inject('user') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $events) { - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); $teamId = $teamId == 'unique()' ? ID::unique() : $teamId; try { - $team = Authorization::skip(fn() => $dbForProject->createDocument('teams', new Document([ + $team = Authorization::skip(fn () => $dbForProject->createDocument('teams', new Document([ '$id' => $teamId, '$permissions' => [ Permission::read(Role::team($teamId)), @@ -85,8 +84,8 @@ App::post('/v1/teams') throw new Exception(Exception::TEAM_ALREADY_EXISTS); } - if (!$isPrivilegedUser && !$isAppUser) { // Don't add user on server mode - if (!\in_array('owner', $roles)) { + if (! $isPrivilegedUser && ! $isAppUser) { // Don't add user on server mode + if (! \in_array('owner', $roles)) { $roles[] = 'owner'; } @@ -110,7 +109,7 @@ App::post('/v1/teams') 'joined' => DateTime::now(), 'confirm' => true, 'secret' => '', - 'search' => implode(' ', [$membershipId, $user->getId()]) + 'search' => implode(' ', [$membershipId, $user->getId()]), ]); $membership = $dbForProject->createDocument('memberships', $membership); @@ -119,7 +118,7 @@ App::post('/v1/teams') $events->setParam('teamId', $team->getId()); - if (!empty($user->getId())) { + if (! empty($user->getId())) { $events->setParam('userId', $user->getId()); } @@ -140,15 +139,14 @@ App::get('/v1/teams') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TEAM_LIST) ->label('sdk.offline.model', '/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -195,7 +193,6 @@ App::get('/v1/teams/:teamId') ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, Response $response, Database $dbForProject) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -221,7 +218,6 @@ App::get('/v1/teams/:teamId/prefs') ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, Response $response, Database $dbForProject) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -256,7 +252,6 @@ App::put('/v1/teams/:teamId') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $name, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $events) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -298,7 +293,6 @@ App::put('/v1/teams/:teamId/prefs') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, array $prefs, Response $response, Database $dbForProject, Event $events) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -331,14 +325,13 @@ App::delete('/v1/teams/:teamId') ->inject('events') ->inject('deletes') ->action(function (string $teamId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); } - if (!$dbForProject->deleteDocument('teams', $teamId)) { + if (! $dbForProject->deleteDocument('teams', $teamId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove team from DB'); } @@ -348,8 +341,7 @@ App::delete('/v1/teams/:teamId') $events ->setParam('teamId', $team->getId()) - ->setPayload($response->output($team, Response::MODEL_TEAM)) - ; + ->setPayload($response->output($team, Response::MODEL_TEAM)); $response->noContent(); }); @@ -375,8 +367,8 @@ App::post('/v1/teams/:teamId/memberships') ->param('email', '', new Email(), 'Email of the new team member.', true) ->param('userId', '', new UID(), 'ID of the user to be added to a team.', true) ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) - ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') - ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation 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, ['clients']) // TODO add our own built-in confirm page + ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 32 characters long.') + ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation 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, ['clients']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) ->inject('response') ->inject('project') @@ -387,14 +379,13 @@ App::post('/v1/teams/:teamId/memberships') ->inject('messaging') ->inject('events') ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, EventPhone $messaging, Event $events) { - if (empty($userId) && empty($email) && empty($phone)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'At least one of userId, email, or phone is required'); } $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); - if (!$isPrivilegedUser && !$isAppUser && empty(App::getEnv('_APP_SMTP_HOST'))) { + if (! $isPrivilegedUser && ! $isAppUser && empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED); } @@ -405,28 +396,28 @@ App::post('/v1/teams/:teamId/memberships') if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); } - if (!empty($userId)) { + if (! empty($userId)) { $invitee = $dbForProject->getDocument('users', $userId); if ($invitee->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND, 'User with given userId doesn\'t exist.', 404); } - if (!empty($email) && $invitee->getAttribute('email', '') !== $email) { + if (! empty($email) && $invitee->getAttribute('email', '') !== $email) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given userId and email doesn\'t match', 409); } - if (!empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { + if (! empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given userId and phone doesn\'t match', 409); } $email = $invitee->getAttribute('email', ''); $phone = $invitee->getAttribute('phone', ''); $name = empty($name) ? $invitee->getAttribute('name', '') : $name; - } elseif (!empty($email)) { + } elseif (! empty($email)) { $invitee = $dbForProject->findOne('users', [Query::equal('email', [$email])]); // Get user by email address - if (!empty($invitee) && !empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { + if (! empty($invitee) && ! empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given email and phone doesn\'t match', 409); } - } elseif (!empty($phone)) { + } elseif (! empty($phone)) { $invitee = $dbForProject->findOne('users', [Query::equal('phone', [$phone])]); - if (!empty($invitee) && !empty($email) && $invitee->getAttribute('email', '') !== $email) { + if (! empty($invitee) && ! empty($email) && $invitee->getAttribute('email', '') !== $email) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given phone and email doesn\'t match', 409); } } @@ -446,13 +437,13 @@ App::post('/v1/teams/:teamId/memberships') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } try { $userId = ID::unique(); - $invitee = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([ + $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ Permission::read(Role::any()), @@ -480,16 +471,16 @@ App::post('/v1/teams/:teamId/memberships') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]) + 'search' => implode(' ', [$userId, $email, $name]), ]))); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isOwner = Authorization::isRole('team:'.$team->getId().'/owner'); - if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) + if (! $isOwner && ! $isPrivilegedUser && ! $isAppUser) { // Not owner, not admin, not app (server) throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to send invitations for this team'); } @@ -514,17 +505,17 @@ App::post('/v1/teams/:teamId/memberships') 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, 'confirm' => ($isPrivilegedUser || $isAppUser), 'secret' => Auth::hash($secret), - 'search' => implode(' ', [$membershipId, $invitee->getId()]) + 'search' => implode(' ', [$membershipId, $invitee->getId()]), ]); if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership try { - $membership = Authorization::skip(fn() => $dbForProject->createDocument('memberships', $membership)); + $membership = Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)); } catch (Duplicate $th) { throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); } $team->setAttribute('total', $team->getAttribute('total', 0) + 1); - $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); + $team = Authorization::skip(fn () => $dbForProject->updateDocument('teams', $team->getId(), $team)); $dbForProject->deleteCachedDocument('users', $invitee->getId()); } else { @@ -537,16 +528,16 @@ App::post('/v1/teams/:teamId/memberships') $url = Template::parseURL($url); $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); $url = Template::unParseURL($url); - if (!empty($email)) { + if (! empty($email)) { $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); - $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); - $subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName); + $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); + $subject = \sprintf($locale->getText('emails.invitation.subject'), $team->getAttribute('name'), $projectName); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; - if ($smtpEnabled && !empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.invitation-'.$locale->default] ?? []; + if ($smtpEnabled && ! empty($customTemplate)) { $body = $customTemplate['message']; $subject = $customTemplate['subject']; $from = $customTemplate['senderName']; @@ -557,13 +548,13 @@ App::post('/v1/teams/:teamId/memberships') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) + ->setParam('{{hello}}', $locale->getText('emails.invitation.hello')) ->setParam('{{name}}', $user->getAttribute('name')) - ->setParam('{{body}}', $locale->getText("emails.invitation.body")) + ->setParam('{{body}}', $locale->getText('emails.invitation.body')) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")) + ->setParam('{{footer}}', $locale->getText('emails.invitation.footer')) + ->setParam('{{thanks}}', $locale->getText('emails.invitation.thanks')) + ->setParam('{{signature}}', $locale->getText('emails.invitation.signature')) ->setParam('{{project}}', $projectName) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -578,13 +569,12 @@ App::post('/v1/teams/:teamId/memberships') ->setFrom($from) ->setRecipient($invitee->getAttribute('email')) ->setName($invitee->getAttribute('name')) - ->trigger() - ; - } elseif (!empty($phone)) { - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); + ->trigger(); + } elseif (! empty($phone)) { + $message = Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; - if (!empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['sms.invitation-'.$locale->default] ?? []; + if (! empty($customTemplate)) { $message = $customTemplate['message']; } @@ -600,8 +590,7 @@ App::post('/v1/teams/:teamId/memberships') $events ->setParam('teamId', $team->getId()) - ->setParam('membershipId', $membership->getId()) - ; + ->setParam('membershipId', $membership->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -627,12 +616,11 @@ App::get('/v1/teams/:teamId/memberships') ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) ->label('sdk.offline.model', '/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('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) ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, array $queries, string $search, Response $response, Database $dbForProject) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -641,7 +629,7 @@ App::get('/v1/teams/:teamId/memberships') $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -676,7 +664,7 @@ App::get('/v1/teams/:teamId/memberships') max: APP_LIMIT_COUNT ); - $memberships = array_filter($memberships, fn(Document $membership) => !empty($membership->getAttribute('userId'))); + $memberships = array_filter($memberships, fn (Document $membership) => ! empty($membership->getAttribute('userId'))); $memberships = array_map(function ($membership) use ($dbForProject, $team) { $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); @@ -684,8 +672,7 @@ App::get('/v1/teams/:teamId/memberships') $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')) - ; + ->setAttribute('userEmail', $user->getAttribute('email')); return $membership; }, $memberships); @@ -714,7 +701,6 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -732,8 +718,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')) - ; + ->setAttribute('userEmail', $user->getAttribute('email')); $response->dynamic($membership, Response::MODEL_MEMBERSHIP); }); @@ -754,14 +739,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') - ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') + ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 32 characters long.') ->inject('request') ->inject('response') ->inject('user') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $events) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -779,9 +763,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isOwner = Authorization::isRole('team:'.$team->getId().'/owner'); - if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) + if (! $isOwner && ! $isPrivilegedUser && ! $isAppUser) { // Not owner, not admin, not app (server) throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles'); } @@ -848,7 +832,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } - $team = Authorization::skip(fn() => $dbForProject->getDocument('teams', $teamId)); + $team = Authorization::skip(fn () => $dbForProject->getDocument('teams', $teamId)); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -859,7 +843,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } if ($userId !== $membership->getAttribute('userId')) { - throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); + throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user ('.$user->getAttribute('email').')'); } if ($user->isEmpty()) { @@ -867,7 +851,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } if ($membership->getAttribute('userId') !== $user->getId()) { - throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); + throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user ('.$user->getAttribute('email').')'); } if ($membership->getAttribute('confirm') === true) { @@ -876,10 +860,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $membership // Attach user to team ->setAttribute('joined', DateTime::now()) - ->setAttribute('confirm', true) - ; + ->setAttribute('confirm', true); - Authorization::skip(fn() => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); + Authorization::skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); // Log user in @@ -917,23 +900,20 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->deleteCachedDocument('users', $user->getId()); - $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); + $team = Authorization::skip(fn () => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); $events ->setParam('teamId', $team->getId()) - ->setParam('membershipId', $membership->getId()) - ; + ->setParam('membershipId', $membership->getId()); - if (!Config::getParam('domainVerification')) { + if (! Config::getParam('domainVerification')) { $response - ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) - ; + ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $response - ->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')) - ; + ->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')); $response->dynamic( $membership @@ -963,7 +943,6 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, Event $events) { - $membership = $dbForProject->getDocument('memberships', $membershipId); if ($membership->isEmpty()) { @@ -998,14 +977,13 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') if ($membership->getAttribute('confirm')) { // Count only confirmed members $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)); - Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); + Authorization::skip(fn () => $dbForProject->updateDocument('teams', $team->getId(), $team)); } $events ->setParam('teamId', $team->getId()) ->setParam('membershipId', $membership->getId()) - ->setPayload($response->output($membership, Response::MODEL_MEMBERSHIP)) - ; + ->setPayload($response->output($membership, Response::MODEL_MEMBERSHIP)); $response->noContent(); }); @@ -1028,7 +1006,6 @@ App::get('/v1/teams/:teamId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1041,13 +1018,13 @@ App::get('/v1/teams/:teamId/logs') $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'team/' . $team->getId(); + $resource = 'team/'.$team->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -1075,14 +1052,14 @@ App::get('/v1/teams/:teamId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'deviceModel' => $device['deviceModel'], ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index cf94135351..f868bdd69e 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2,43 +2,43 @@ use Appwrite\Auth\Auth; use Appwrite\Auth\Validator\Password; +use Appwrite\Auth\Validator\PasswordDictionary; +use Appwrite\Auth\Validator\PasswordHistory; +use Appwrite\Auth\Validator\PersonalData; use Appwrite\Auth\Validator\Phone; use Appwrite\Detector\Detector; use Appwrite\Event\Delete; use Appwrite\Event\Event; +use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Appwrite\Utopia\Database\Validator\CustomId; -use Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Database\Validator\Queries\Users; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Response; +use MaxMind\Db\Reader; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Locale\Locale; -use Appwrite\Extend\Exception; -use Utopia\Database\Document; -use Utopia\Database\DateTime; -use Utopia\Database\Exception\Duplicate; -use Utopia\Database\Validator\UID; -use Utopia\Database\Database; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; +use Utopia\Database\Validator\UID; +use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; -use Utopia\Validator\WhiteList; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; -use MaxMind\Db\Reader; use Utopia\Validator\Integer; -use Appwrite\Auth\Validator\PasswordHistory; -use Appwrite\Auth\Validator\PasswordDictionary; -use Appwrite\Auth\Validator\PersonalData; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; /** TODO: Remove function when we move to using utopia/platform */ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $email, ?string $password, ?string $phone, string $name, Document $project, Database $dbForProject, Event $events): Document @@ -46,14 +46,14 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e $hashOptionsObject = (\is_string($hashOptions)) ? \json_decode($hashOptions, true) : $hashOptions; // Cast to JSON array $passwordHistory = $project->getAttribute('auths', [])['passwordHistory'] ?? 0; - if (!empty($email)) { + if (! empty($email)) { $email = \strtolower($email); // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } } @@ -65,12 +65,12 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($userId, $email, $name, $phone); - if (!$personalDataValidator->isValid($password)) { + if (! $personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } - $password = (!empty($password)) ? ($hash === 'plaintext' ? Auth::passwordHash($password, $hash, $hashOptionsObject) : $password) : null; + $password = (! empty($password)) ? ($hash === 'plaintext' ? Auth::passwordHash($password, $hash, $hashOptionsObject) : $password) : null; $user = $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ @@ -86,7 +86,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e 'labels' => [], 'password' => $password, 'passwordHistory' => is_null($password) && $passwordHistory === 0 ? [] : [$password], - 'passwordUpdate' => (!empty($password)) ? DateTime::now() : null, + 'passwordUpdate' => (! empty($password)) ? DateTime::now() : null, 'hash' => $hash === 'plaintext' ? Auth::DEFAULT_ALGO : $hash, 'hashOptions' => $hash === 'plaintext' ? Auth::DEFAULT_ALGO_OPTIONS : $hashOptionsObject + ['type' => $hash], 'registration' => DateTime::now(), @@ -96,7 +96,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $phone, $name]) + 'search' => implode(' ', [$userId, $email, $phone, $name]), ])); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); @@ -131,7 +131,6 @@ App::post('/v1/users') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, ?string $email, ?string $phone, ?string $password, string $name, Response $response, Document $project, Database $dbForProject, Event $events) { - $user = createUser('plaintext', '{}', $userId, $email, $password, $phone, $name, $project, $dbForProject, $events); $response @@ -255,8 +254,8 @@ App::post('/v1/users/sha') ->action(function (string $userId, string $email, string $password, string $passwordVersion, string $name, Response $response, Document $project, Database $dbForProject, Event $events) { $options = '{}'; - if (!empty($passwordVersion)) { - $options = '{"version":"' . $passwordVersion . '"}'; + if (! empty($passwordVersion)) { + $options = '{"version":"'.$passwordVersion.'"}'; } $user = createUser('sha', $options, $userId, $email, $password, null, $name, $project, $dbForProject, $events); @@ -329,7 +328,7 @@ App::post('/v1/users/scrypt') 'costCpu' => $passwordCpu, 'costMemory' => $passwordMemory, 'costParallel' => $passwordParallel, - 'length' => $passwordLength + 'length' => $passwordLength, ]; $user = createUser('scrypt', \json_encode($options), $userId, $email, $password, null, $name, $project, $dbForProject, $events); @@ -365,7 +364,7 @@ App::post('/v1/users/scrypt-modified') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $email, string $password, string $passwordSalt, string $passwordSaltSeparator, string $passwordSignerKey, string $name, Response $response, Document $project, Database $dbForProject, Event $events) { - $user = createUser('scryptMod', '{"signerKey":"' . $passwordSignerKey . '","saltSeparator":"' . $passwordSaltSeparator . '","salt":"' . $passwordSalt . '"}', $userId, $email, $password, null, $name, $project, $dbForProject, $events); + $user = createUser('scryptMod', '{"signerKey":"'.$passwordSignerKey.'","saltSeparator":"'.$passwordSaltSeparator.'","salt":"'.$passwordSalt.'"}', $userId, $email, $password, null, $name, $project, $dbForProject, $events); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -406,7 +405,7 @@ App::post('/v1/users/:userId/targets') $target = $dbForProject->getDocument('targets', $targetId); - if (!$target->isEmpty()) { + if (! $target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); } @@ -414,7 +413,7 @@ App::post('/v1/users/:userId/targets') '$id' => $targetId, // TO DO: what permissions should be given when created a target. '$permissions' => [ - Permission::read(Role::any()) + Permission::read(Role::any()), ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), @@ -442,15 +441,14 @@ App::get('/v1/users') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_USER_LIST) - ->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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -492,7 +490,6 @@ App::get('/v1/users/:userId') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -517,7 +514,6 @@ App::get('/v1/users/:userId/prefs') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -545,7 +541,6 @@ App::get('/v1/users/:userId/targets/:targetId') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, string $targetId, Response $response, Database $dbForProject) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -577,7 +572,6 @@ App::get('/v1/users/:userId/sessions') ->inject('dbForProject') ->inject('locale') ->action(function (string $userId, Response $response, Database $dbForProject, Locale $locale) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -588,8 +582,7 @@ App::get('/v1/users/:userId/sessions') foreach ($sessions as $key => $session) { /** @var Document $session */ - - $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session->setAttribute('countryName', $countryName); $session->setAttribute('current', false); @@ -617,7 +610,6 @@ App::get('/v1/users/:userId/memberships') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -659,7 +651,6 @@ App::get('/v1/users/:userId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -678,7 +669,7 @@ App::get('/v1/users/:userId/logs') $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -702,14 +693,14 @@ App::get('/v1/users/:userId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'deviceModel' => $device['deviceModel'], ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -737,7 +728,6 @@ App::get('/v1/users/:userId/targets') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -763,15 +753,14 @@ App::get('/v1/users/identities') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) - ->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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - if (!empty($search)) { + if (! empty($search)) { $queries[] = Query::search('search', $search); } @@ -819,7 +808,6 @@ App::patch('/v1/users/:userId/status') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $status, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -856,7 +844,6 @@ App::put('/v1/users/:userId/labels') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, array $labels, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -893,7 +880,6 @@ App::patch('/v1/users/:userId/verification') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $emailVerification, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -928,7 +914,6 @@ App::patch('/v1/users/:userId/verification/phone') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $phoneVerification, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -964,7 +949,6 @@ App::patch('/v1/users/:userId/name') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $name, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1002,7 +986,6 @@ App::patch('/v1/users/:userId/password') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $password, Response $response, Document $project, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1011,7 +994,7 @@ App::patch('/v1/users/:userId/password') if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($userId, $user->getAttribute('email'), $user->getAttribute('name'), $user->getAttribute('phone')); - if (!$personalDataValidator->isValid($password)) { + if (! $personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } @@ -1022,7 +1005,7 @@ App::patch('/v1/users/:userId/password') $history = $user->getAttribute('passwordHistory', []); if ($historyLimit > 0) { $validator = new PasswordHistory($history, $user->getAttribute('hash'), $user->getAttribute('hashOptions')); - if (!$validator->isValid($password)) { + if (! $validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -1065,7 +1048,6 @@ App::patch('/v1/users/:userId/email') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $email, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1079,15 +1061,13 @@ App::patch('/v1/users/:userId/email') Query::equal('providerEmail', [$email]), Query::notEqual('userId', $user->getId()), ]); - if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } $user ->setAttribute('email', $email) - ->setAttribute('emailVerification', false) - ; - + ->setAttribute('emailVerification', false); try { $user = $dbForProject->updateDocument('users', $user->getId(), $user); @@ -1120,7 +1100,6 @@ App::patch('/v1/users/:userId/phone') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $number, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1129,8 +1108,7 @@ App::patch('/v1/users/:userId/phone') $user ->setAttribute('phone', $number) - ->setAttribute('phoneVerification', false) - ; + ->setAttribute('phoneVerification', false); try { $user = $dbForProject->updateDocument('users', $user->getId(), $user); @@ -1164,7 +1142,6 @@ App::patch('/v1/users/:userId/verification') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $emailVerification, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1196,7 +1173,6 @@ App::patch('/v1/users/:userId/prefs') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, array $prefs, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1230,7 +1206,6 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1276,7 +1251,6 @@ App::delete('/v1/users/:userId/sessions/:sessionId') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $sessionId, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1318,7 +1292,6 @@ App::delete('/v1/users/:userId/sessions') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1361,7 +1334,6 @@ App::delete('/v1/users/:userId') ->inject('events') ->inject('deletes') ->action(function (string $userId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1402,7 +1374,6 @@ App::delete('/v1/users/:userId/targets/:targetId') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { - $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1449,7 +1420,6 @@ App::delete('/v1/users/identities/:identityId') ->inject('events') ->inject('deletes') ->action(function (string $identityId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { - $identity = $dbForProject->getDocument('identities', $identityId); if ($identity->isEmpty()) { @@ -1476,7 +1446,6 @@ App::get('/v1/users/usage') ->inject('dbForProject') ->inject('register') ->action(function (string $range, Response $response, Database $dbForProject) { - $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -1509,22 +1478,22 @@ App::get('/v1/users/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } } - } $response->dynamic(new Document([ 'range' => $range, - 'usersTotal' => $usage[$metrics[0]], + 'usersTotal' => $usage[$metrics[0]], 'sessionsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_USERS); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index e8d6bb225a..bbd3d45f31 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1,38 +1,38 @@ getHostname(); $domains = Config::getParam('domains', []); - if (!array_key_exists($domain, $domains)) { - $domain = new Domain(!empty($domain) ? $domain : ''); + if (! array_key_exists($domain, $domains)) { + $domain = new Domain(! empty($domain) ? $domain : ''); - if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { + if (empty($domain->get()) || ! $domain->isKnown() || $domain->isTest()) { $domains[$domain->get()] = false; - Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); + Console::warning($domain->get().' is not a publicly accessible domain. Skipping SSL certificate generation.'); } elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { Console::warning('Skipping SSL certificates generation on ACME challenge.'); } else { @@ -97,7 +97,7 @@ App::init() $envDomain = App::getEnv('_APP_DOMAIN', ''); $mainDomain = null; - if (!empty($envDomain) && $envDomain !== 'localhost') { + if (! empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; } else { $domainDocument = $dbForConsole->findOne('domains', [Query::orderAsc('_id')]); @@ -105,13 +105,13 @@ App::init() } if ($mainDomain !== $domain->get()) { - Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); + Console::warning($domain->get().' is not a main domain. Skipping SSL certificate generation.'); } else { $domainDocument = $dbForConsole->findOne('domains', [ - Query::equal('domain', [$domain->get()]) + Query::equal('domain', [$domain->get()]), ]); - if (!$domainDocument) { + if (! $domainDocument) { $domainDocument = new Document([ 'domain' => $domain->get(), 'tld' => $domain->getSuffix(), @@ -122,7 +122,7 @@ App::init() $domainDocument = $dbForConsole->createDocument('domains', $domainDocument); - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + Console::info('Issuing a TLS certificate for the main domain ('.$domain->get().') in a few seconds...'); (new Certificate()) ->setDomain($domainDocument) @@ -145,7 +145,7 @@ App::init() throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } - if (!empty($route->getLabel('sdk.auth', [])) && $project->isEmpty() && ($route->getLabel('scope', '') !== 'public')) { + if (! empty($route->getLabel('sdk.auth', [])) && $project->isEmpty() && ($route->getLabel('scope', '') !== 'public')) { throw new AppwriteException(AppwriteException::PROJECT_UNKNOWN); } @@ -160,14 +160,14 @@ App::init() $refDomainOrigin = $origin; } - $refDomain = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $refDomainOrigin . (!empty($port) ? ':' . $port : ''); + $refDomain = (! empty($protocol) ? $protocol : $request->getProtocol()).'://'.$refDomainOrigin.(! empty($port) ? ':'.$port : ''); - $refDomain = (!$route->getLabel('origin', false)) // This route is publicly accessible + $refDomain = (! $route->getLabel('origin', false)) // This route is publicly accessible ? $refDomain - : (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); + : (! empty($protocol) ? $protocol : $request->getProtocol()).'://'.$origin.(! empty($port) ? ':'.$port : ''); $selfDomain = new Domain($request->getHostname()); - $endDomain = new Domain((string)$origin); + $endDomain = new Domain((string) $origin); Config::setParam( 'domainVerification', @@ -175,7 +175,7 @@ App::init() $endDomain->getRegisterable() !== '' ); - $isLocalHost = $request->getHostname() === 'localhost' || $request->getHostname() === 'localhost:' . $request->getPort(); + $isLocalHost = $request->getHostname() === 'localhost' || $request->getHostname() === 'localhost:'.$request->getPort(); $isIpAddress = filter_var($request->getHostname(), FILTER_VALIDATE_IP) !== false; $isConsoleProject = $project->getAttribute('$id', '') === 'console'; @@ -186,8 +186,8 @@ App::init() $isLocalHost || $isIpAddress ? null : ($isConsoleProject && $isConsoleRootSession - ? '.' . $selfDomain->getRegisterable() - : '.' . $request->getHostname() + ? '.'.$selfDomain->getRegisterable() + : '.'.$request->getHostname() ) ); @@ -231,12 +231,12 @@ App::init() throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP.'); } - return $response->redirect('https://' . $request->getHostname() . $request->getURI()); + return $response->redirect('https://'.$request->getHostname().$request->getURI()); } } if ($request->getProtocol() === 'https') { - $response->addHeader('Strict-Transport-Security', 'max-age=' . (60 * 60 * 24 * 126)); // 126 days + $response->addHeader('Strict-Transport-Security', 'max-age='.(60 * 60 * 24 * 126)); // 126 days } $response @@ -246,8 +246,7 @@ App::init() ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma') ->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $refDomain) - ->addHeader('Access-Control-Allow-Credentials', 'true') - ; + ->addHeader('Access-Control-Allow-Credentials', 'true'); /* * Validate Client Domain - Check to avoid CSRF attack @@ -258,7 +257,7 @@ App::init() $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); if ( - !$originValidator->isValid($origin) + ! $originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) @@ -298,7 +297,7 @@ App::init() $authKey = $request->getHeader('x-appwrite-key', ''); - if (!empty($authKey)) { // API Key authentication + if (! empty($authKey)) { // API Key authentication // Check if given key match project API keys $key = $project->find('secret', $authKey, 'keys'); @@ -310,7 +309,7 @@ App::init() $user = new Document([ '$id' => '', 'status' => true, - 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), + 'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(), 'password' => '', 'name' => $project->getAttribute('name', 'Untitled'), ]); @@ -319,8 +318,8 @@ App::init() $scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', [])); $expire = $key->getAttribute('expire'); - if (!empty($expire) && $expire < DateTime::formatTz(DateTime::now())) { - throw new AppwriteException(AppwriteException:: PROJECT_KEY_EXPIRED); + if (! empty($expire) && $expire < DateTime::formatTz(DateTime::now())) { + throw new AppwriteException(AppwriteException::PROJECT_KEY_EXPIRED); } Authorization::setRole(Auth::USER_ROLE_APPS); @@ -337,7 +336,7 @@ App::init() $sdk = $request->getHeader('x-sdk-name', 'UNKNOWN'); if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); - if (!in_array($sdk, $sdks)) { + if (! in_array($sdk, $sdks)) { array_push($sdks, $sdk); $key->setAttribute('sdks', $sdks); @@ -357,22 +356,22 @@ App::init() } $service = $route->getLabel('sdk.namespace', ''); - if (!empty($service)) { + if (! empty($service)) { if ( array_key_exists($service, $project->getAttribute('services', [])) - && !$project->getAttribute('services', [])[$service] - && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) + && ! $project->getAttribute('services', [])[$service] + && ! (Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED); } } - if (!\in_array($scope, $scopes)) { + if (! \in_array($scope, $scopes)) { if ($project->isEmpty()) { // Check if permission is denied because project is missing throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } - throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')'); + throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User').' (role: '.\strtolower($roles[$role]['label']).') missing scope ('.$scope.')'); } if (false === $user->getAttribute('status')) { // Account is blocked @@ -388,7 +387,6 @@ App::options() ->inject('request') ->inject('response') ->action(function (Request $request, Response $response) { - $origin = $request->getOrigin(); $response @@ -410,7 +408,6 @@ App::error() ->inject('logger') ->inject('loggerBreadcrumbs') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, array $loggerBreadcrumbs) { - $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->match($request); @@ -425,11 +422,11 @@ App::error() $log = new Utopia\Logger\Log(); - if (isset($user) && !$user->isEmpty()) { + if (isset($user) && ! $user->isEmpty()) { $log->setUser(new User($user->getId())); } - $log->setNamespace("http"); + $log->setNamespace('http'); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); @@ -442,7 +439,7 @@ App::error() $log->addTag('code', $error->getCode()); $log->addTag('projectId', $project->getId()); $log->addTag('hostname', $request->getHostname()); - $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); + $log->addTag('locale', (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); @@ -450,7 +447,7 @@ App::error() $log->addExtra('detailedTrace', $error->getTrace()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); + $action = $route->getLabel('sdk.namespace', 'UNKNOWN_NAMESPACE').'.'.$route->getLabel('sdk.method', 'UNKNOWN_METHOD'); $log->setAction($action); $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; @@ -461,7 +458,7 @@ App::error() } $responseCode = $logger->addLog($log); - Console::info('Log pushed with status code: ' . $responseCode); + Console::info('Log pushed with status code: '.$responseCode); } } @@ -472,17 +469,17 @@ App::error() $trace = $error->getTrace(); if (php_sapi_name() === 'cli') { - Console::error('[Error] Timestamp: ' . date('c', time())); + Console::error('[Error] Timestamp: '.date('c', time())); if ($route) { - Console::error('[Error] Method: ' . $route->getMethod()); - Console::error('[Error] URL: ' . $route->getPath()); + Console::error('[Error] Method: '.$route->getMethod()); + Console::error('[Error] URL: '.$route->getPath()); } - Console::error('[Error] Type: ' . get_class($error)); - Console::error('[Error] Message: ' . $message); - Console::error('[Error] File: ' . $file); - Console::error('[Error] Line: ' . $line); + Console::error('[Error] Type: '.get_class($error)); + Console::error('[Error] Message: '.$message); + Console::error('[Error] File: '.$file); + Console::error('[Error] Line: '.$line); } /** Handle Utopia Errors */ @@ -503,7 +500,7 @@ App::error() } /** Wrap all exceptions inside Appwrite\Extend\Exception */ - if (!($error instanceof AppwriteException)) { + if (! ($error instanceof AppwriteException)) { $error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error); } @@ -548,8 +545,7 @@ App::error() ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') ->addHeader('Expires', '0') ->addHeader('Pragma', 'no-cache') - ->setStatusCode($code) - ; + ->setStatusCode($code); $template = ($route) ? $route->getLabel('error', null) : null; @@ -557,15 +553,14 @@ App::error() $layout = new View($template); $layout - ->setParam('title', $project->getAttribute('name') . ' - Error') + ->setParam('title', $project->getAttribute('name').' - Error') ->setParam('development', App::isDevelopment()) ->setParam('projectName', $project->getAttribute('name')) ->setParam('projectURL', $project->getAttribute('url')) ->setParam('message', $error->getMessage()) ->setParam('type', $type) ->setParam('code', $code) - ->setParam('trace', $trace) - ; + ->setParam('trace', $trace); $response->html($layout->render()); } @@ -582,7 +577,7 @@ App::get('/robots.txt') ->label('docs', false) ->inject('response') ->action(function (Response $response) { - $template = new View(__DIR__ . '/../views/general/robots.phtml'); + $template = new View(__DIR__.'/../views/general/robots.phtml'); $response->text($template->render(false)); }); @@ -592,7 +587,7 @@ App::get('/humans.txt') ->label('docs', false) ->inject('response') ->action(function (Response $response) { - $template = new View(__DIR__ . '/../views/general/humans.phtml'); + $template = new View(__DIR__.'/../views/general/humans.phtml'); $response->text($template->render(false)); }); @@ -611,43 +606,43 @@ App::get('/.well-known/acme-challenge/*') ...Text::ALPHABET_LOWER, ...Text::ALPHABET_UPPER, '-', - '_' + '_', ]); - if (!$validator->isValid($token) || \count($uriChunks) !== 4) { + if (! $validator->isValid($token) || \count($uriChunks) !== 4) { throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, 'Invalid challenge token.'); } $base = \realpath(APP_STORAGE_CERTIFICATES); - $absolute = \realpath($base . '/.well-known/acme-challenge/' . $token); + $absolute = \realpath($base.'/.well-known/acme-challenge/'.$token); - if (!$base) { + if (! $base) { throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Storage error'); } - if (!$absolute) { + if (! $absolute) { throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND, 'Unknown path'); } - if (!\substr($absolute, 0, \strlen($base)) === $base) { + if (! \substr($absolute, 0, \strlen($base)) === $base) { throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, 'Invalid path'); } - if (!\file_exists($absolute)) { + if (! \file_exists($absolute)) { throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND, 'Unknown path'); } $content = @\file_get_contents($absolute); - if (!$content) { + if (! $content) { throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Failed to get contents'); } $response->text($content); }); -include_once __DIR__ . '/shared/api.php'; -include_once __DIR__ . '/shared/api/auth.php'; +include_once __DIR__.'/shared/api.php'; +include_once __DIR__.'/shared/api/auth.php'; foreach (Config::getParam('services', []) as $service) { include_once $service['controller']; diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 892c41d872..779c361b61 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -3,18 +3,18 @@ global $utopia, $request, $response; use Appwrite\Extend\Exception; -use Utopia\Database\Document; -use Utopia\Validator\Host; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; -use Utopia\Validator\ArrayList; -use Utopia\Validator\Integer; -use Utopia\Validator\Text; -use Utopia\Storage\Validator\File; -use Utopia\Validator\WhiteList; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; +use Utopia\Storage\Validator\File; +use Utopia\Validator\ArrayList; +use Utopia\Validator\Host; +use Utopia\Validator\Integer; use Utopia\Validator\Nullable; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; App::get('/v1/mock/tests/foo') ->desc('Get Foo') @@ -220,9 +220,9 @@ App::get('/v1/mock/tests/general/headers') 'x-sdk-version' => $request->getHeader('x-sdk-version'), ]; $res = array_map(function ($key, $value) { - return $key . ': ' . $value; + return $key.': '.$value; }, array_keys($res), $res); - $res = implode("; ", $res); + $res = implode('; ', $res); $response->dynamic(new Document(['result' => $res]), Response::MODEL_MOCK); }); @@ -241,14 +241,12 @@ App::get('/v1/mock/tests/general/download') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { - $response ->setContentType('text/plain') ->addHeader('Content-Disposition', 'attachment; filename="test.txt"') - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache ->addHeader('X-Peak', \memory_get_peak_usage()) - ->send("GET:/v1/mock/tests/general/download:passed") - ; + ->send('GET:/v1/mock/tests/general/download:passed'); }); App::post('/v1/mock/tests/general/upload') @@ -271,14 +269,13 @@ App::post('/v1/mock/tests/general/upload') ->inject('request') ->inject('response') ->action(function (string $x, int $y, array $z, mixed $file, Request $request, Response $response) { - $file = $request->getFiles('file'); $contentRange = $request->getHeader('content-range'); $chunkSize = 5 * 1024 * 1024; // 5MB - if (!empty($contentRange)) { + if (! empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $size = $request->getContentRangeSize(); @@ -293,7 +290,7 @@ App::post('/v1/mock/tests/general/upload') throw new Exception(Exception::GENERAL_MOCK, 'Invalid content-range header'); } - if ($start === 0 && !empty($id)) { + if ($start === 0 && ! empty($id)) { throw new Exception(Exception::GENERAL_MOCK, 'First chunked request cannot have id header'); } @@ -317,7 +314,7 @@ App::post('/v1/mock/tests/general/upload') $response->json([ '$id' => ID::custom('newfileid'), 'chunksTotal' => (int) ceil($size / ($end + 1 - $start)), - 'chunksUploaded' => ceil($start / $chunkSize) + 1 + 'chunksUploaded' => ceil($start / $chunkSize) + 1, ]); } } else { @@ -330,7 +327,7 @@ App::post('/v1/mock/tests/general/upload') } if ($file['size'] !== 38756) { - throw new Exception(Exception::GENERAL_MOCK, 'Wrong file size'); + throw new Exception(Exception::GENERAL_MOCK, 'Wrong file size'); } if (\md5(\file_get_contents($file['tmp_name'])) !== 'd80e7e6999a3eb2ae0d631a96fe135a4') { @@ -353,7 +350,6 @@ App::get('/v1/mock/tests/general/redirect') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { - $response->redirect('/v1/mock/tests/general/redirect/done'); }); @@ -387,7 +383,6 @@ App::get('/v1/mock/tests/general/set-cookie') ->inject('response') ->inject('request') ->action(function (Response $response, Request $request) { - $response->addCookie('cookieName', 'cookieValue', \time() + 31536000, '/', $request->getHostname(), true, true); }); @@ -405,7 +400,6 @@ App::get('/v1/mock/tests/general/get-cookie') ->label('sdk.mock', true) ->inject('request') ->action(function (Request $request) { - if ($request->getCookie('cookieName', '') !== 'cookieValue') { throw new Exception(Exception::GENERAL_MOCK, 'Missing cookie value'); } @@ -424,7 +418,6 @@ App::get('/v1/mock/tests/general/empty') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { - $response->noContent(); }); @@ -465,9 +458,9 @@ App::get('/v1/mock/tests/general/headers') 'x-sdk-version' => $request->getHeader('x-sdk-version'), ]; $res = array_map(function ($key, $value) { - return $key . ': ' . $value; + return $key.': '.$value; }, array_keys($res), $res); - $res = implode("; ", $res); + $res = implode('; ', $res); $response->dynamic(new Document(['result' => $res]), Response::MODEL_MOCK); }); @@ -518,11 +511,9 @@ App::get('/v1/mock/tests/general/502-error') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { - $response ->setStatusCode(502) - ->text('This is a text error') - ; + ->text('This is a text error'); }); App::get('/v1/mock/tests/general/oauth2') @@ -537,8 +528,7 @@ App::get('/v1/mock/tests/general/oauth2') ->param('state', '', new Text(1024), 'OAuth2 state.') ->inject('response') ->action(function (string $client_id, string $redirectURI, string $scope, string $state, Response $response) { - - $response->redirect($redirectURI . '?' . \http_build_query(['code' => 'abcdef', 'state' => $state])); + $response->redirect($redirectURI.'?'.\http_build_query(['code' => 'abcdef', 'state' => $state])); }); App::get('/v1/mock/tests/general/oauth2/token') @@ -555,7 +545,6 @@ App::get('/v1/mock/tests/general/oauth2/token') ->param('refresh_token', '', new Text(100), 'OAuth2 refresh token.', true) ->inject('response') ->action(function (string $client_id, string $client_secret, string $grantType, string $redirectURI, string $code, string $refreshToken, Response $response) { - if ($client_id != '1') { throw new Exception(Exception::GENERAL_MOCK, 'Invalid client ID'); } @@ -567,7 +556,7 @@ App::get('/v1/mock/tests/general/oauth2/token') $responseJson = [ 'access_token' => '123456', 'refresh_token' => 'tuvwxyz', - 'expires_in' => 14400 + 'expires_in' => 14400, ]; if ($grantType === 'authorization_code') { @@ -595,7 +584,6 @@ App::get('/v1/mock/tests/general/oauth2/user') ->param('token', '', new Text(100), 'OAuth2 Access Token.') ->inject('response') ->action(function (string $token, Response $response) { - if ($token != '123456') { throw new Exception(Exception::GENERAL_MOCK, 'Invalid token'); } @@ -614,7 +602,6 @@ App::get('/v1/mock/tests/general/oauth2/success') ->label('docs', false) ->inject('response') ->action(function (Response $response) { - $response->json([ 'result' => 'success', ]); @@ -627,7 +614,6 @@ App::get('/v1/mock/tests/general/oauth2/failure') ->label('docs', false) ->inject('response') ->action(function (Response $response) { - $response ->setStatusCode(Response::STATUS_CODE_BAD_REQUEST) ->json([ @@ -641,23 +627,22 @@ App::shutdown() ->inject('response') ->inject('request') ->action(function (App $utopia, Response $response, Request $request) { - $result = []; - $route = $utopia->match($request); - $path = APP_STORAGE_CACHE . '/tests.json'; - $tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : []; + $route = $utopia->match($request); + $path = APP_STORAGE_CACHE.'/tests.json'; + $tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : []; - if (!\is_array($tests)) { + if (! \is_array($tests)) { throw new Exception(Exception::GENERAL_MOCK, 'Failed to read results', 500); } - $result[$route->getMethod() . ':' . $route->getPath()] = true; + $result[$route->getMethod().':'.$route->getPath()] = true; $tests = \array_merge($tests, $result); - if (!\file_put_contents($path, \json_encode($tests), LOCK_EX)) { + if (! \file_put_contents($path, \json_encode($tests), LOCK_EX)) { throw new Exception(Exception::GENERAL_MOCK, 'Failed to save results', 500); } - $response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getPath() . ':passed']), Response::MODEL_MOCK); + $response->dynamic(new Document(['result' => $route->getMethod().':'.$route->getPath().':passed']), Response::MODEL_MOCK); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 2bbac41811..ad7b3d135d 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -7,14 +7,14 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\Mail; -use Appwrite\Extend\Exception; use Appwrite\Event\Usage; +use Appwrite\Extend\Exception; use Appwrite\Messaging\Adapter\Realtime; -use Appwrite\Utopia\Response; use Appwrite\Utopia\Request; -use Utopia\App; +use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; +use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; use Utopia\Database\Database; @@ -36,7 +36,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar $replace = $parts[1] ?? ''; $params = match ($namespace) { - 'user' => (array)$user, + 'user' => (array) $user, 'request' => $requestParams, default => $responsePayload, }; @@ -45,11 +45,11 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar $label = \str_replace($find, $params[$replace], $label); } } + return $label; }; $databaseListener = function (string $event, Document $document, Document $project, Usage $queueForUsage, Database $dbForProject) { - $value = 1; if ($event === Database::EVENT_DOCUMENT_DELETE) { $value = -1; @@ -81,13 +81,13 @@ $databaseListener = function (string $event, Document $document, Document $proje ->addReduce($document); } break; - case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections + case str_starts_with($document->getCollection(), 'database_') && ! str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; $queueForUsage ->addMetric(METRIC_COLLECTIONS, $value) // per project ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value) // per database - ; +; if ($event === Database::EVENT_DOCUMENT_DELETE) { $queueForUsage @@ -96,7 +96,7 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_'): //documents $parts = explode('_', $document->getCollection()); - $databaseInternalId = $parts[1] ?? 0; + $databaseInternalId = $parts[1] ?? 0; $collectionInternalId = $parts[3] ?? 0; $queueForUsage ->addMetric(METRIC_DOCUMENTS, $value) // per project @@ -132,13 +132,13 @@ $databaseListener = function (string $event, Document $document, Document $proje ->addMetric(METRIC_DEPLOYMENTS, $value) // per project ->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value)// per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);// per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value); // per function break; case $document->getCollection() === 'executions': $queueForUsage ->addMetric(METRIC_EXECUTIONS, $value) // per project - ->addMetric(str_replace('{functionInternalId}', $document->getAttribute('functionInternalId'), METRIC_FUNCTION_ID_EXECUTIONS), $value);// per function + ->addMetric(str_replace('{functionInternalId}', $document->getAttribute('functionInternalId'), METRIC_FUNCTION_ID_EXECUTIONS), $value); // per function break; default: break; @@ -161,7 +161,6 @@ App::init() ->inject('mode') ->inject('mails') ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Delete $deletes, EventDatabase $database, Database $dbForProject, Usage $queueForUsage, string $mode, Mail $mails) use ($databaseListener) { - $route = $utopia->match($request); if ($project->isEmpty() && $route->getLabel('abuse-limit', 0) > 0) { // Abuse limit requires an active project scope @@ -174,7 +173,7 @@ App::init() $abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}'); $timeLimitArray = []; - $abuseKeyLabel = (!is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel; + $abuseKeyLabel = (! is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel; foreach ($abuseKeyLabel as $abuseKey) { $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject); @@ -182,7 +181,7 @@ App::init() ->setParam('{userId}', $user->getId()) ->setParam('{userAgent}', $request->getUserAgent('')) ->setParam('{ip}', $request->getIP()) - ->setParam('{url}', $request->getHostname() . $route->getPath()) + ->setParam('{url}', $request->getHostname().$route->getPath()) ->setParam('{method}', $request->getMethod()); $timeLimitArray[] = $timeLimit; } @@ -195,8 +194,8 @@ App::init() foreach ($timeLimitArray as $timeLimit) { foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys - if (!empty($value)) { - $timeLimit->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value); + if (! empty($value)) { + $timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value); } } @@ -210,16 +209,15 @@ App::init() $response ->addHeader('X-RateLimit-Limit', $limit) ->addHeader('X-RateLimit-Remaining', $remaining) - ->addHeader('X-RateLimit-Reset', $time) - ; + ->addHeader('X-RateLimit-Reset', $time); } $enabled = App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; if ( $enabled // Abuse is enabled - && !$isAppUser // User is not API key - && !$isPrivilegedUser // User is not an admin + && ! $isAppUser // User is not API key + && ! $isPrivilegedUser // User is not an admin && $abuse->check() // Route is rate-limited ) { throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); @@ -243,7 +241,7 @@ App::init() ->setUser($user); $smtp = $project->getAttribute('smtp', []); - if (!empty($smtp) && ($smtp['enabled'] ?? false)) { + if (! empty($smtp) && ($smtp['enabled'] ?? false)) { $mails ->setSmtpHost($smtp['host'] ?? '') ->setSmtpPort($smtp['port'] ?? 25) @@ -265,14 +263,14 @@ App::init() $useCache = $route->getLabel('cache', false); if ($useCache) { - $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; + $key = md5($request->getURI().implode('*', $request->getParams())).'*'.APP_CACHE_BUSTER; $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) + new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$project->getId()) ); $timestamp = 60 * 60 * 24 * 30; $data = $cache->load($key, $timestamp); - if (!empty($data)) { + if (! empty($data)) { $data = json_decode($data, true); $parts = explode('/', $data['resourceType']); $type = $parts[0] ?? null; @@ -282,24 +280,24 @@ App::init() $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { + if (! $fileSecurity && ! $valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $parts = explode('/', $data['resource']); $fileId = $parts[1] ?? null; - if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + if ($fileSecurity && ! $valid) { + $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -308,11 +306,10 @@ App::init() } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp).' GMT') ->addHeader('X-Appwrite-Cache', 'hit') ->setContentType($data['contentType']) - ->send(base64_decode($data['payload'])) - ; + ->send(base64_decode($data['payload'])); $route->setIsActive(false); } else { @@ -327,7 +324,6 @@ App::init() ->inject('request') ->inject('project') ->action(function (App $utopia, Request $request, Document $project) { - $route = $utopia->match($request); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -431,10 +427,9 @@ App::shutdown() ->inject('mode') ->inject('dbForConsole') ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Delete $deletes, EventDatabase $database, Database $dbForProject, Func $queueForFunctions, Usage $queueForUsage, string $mode, Database $dbForConsole) use ($parseLabel) { - $responsePayload = $response->getPayload(); - if (!empty($events->getEvent())) { + if (! empty($events->getEvent())) { if (empty($events->getPayload())) { $events->setPayload($responsePayload); } @@ -483,7 +478,7 @@ App::shutdown() roles: $target['roles'], options: [ 'permissionsChanged' => $target['permissionsChanged'], - 'userId' => $events->getParam('userId') + 'userId' => $events->getParam('userId'), ] ); } @@ -496,24 +491,24 @@ App::shutdown() * Audit labels */ $pattern = $route->getLabel('audits.resource', null); - if (!empty($pattern)) { + if (! empty($pattern)) { $resource = $parseLabel($pattern, $responsePayload, $requestParams, $user); - if (!empty($resource) && $resource !== $pattern) { + if (! empty($resource) && $resource !== $pattern) { $audits->setResource($resource); } } - if (!$user->isEmpty()) { + if (! $user->isEmpty()) { $audits->setUser($user); } - if (!empty($audits->getResource()) && !empty($audits->getUser()->getId())) { + if (! empty($audits->getResource()) && ! empty($audits->getUser()->getId())) { /** * audits.payload is switched to default true * in order to auto audit payload for all endpoints */ $pattern = $route->getLabel('audits.payload', true); - if (!empty($pattern)) { + if (! empty($pattern)) { $audits->setPayload($responsePayload); } @@ -523,11 +518,11 @@ App::shutdown() $audits->trigger(); } - if (!empty($deletes->getType())) { + if (! empty($deletes->getType())) { $deletes->trigger(); } - if (!empty($database->getType())) { + if (! empty($database->getType())) { $database->trigger(); } @@ -539,35 +534,35 @@ App::shutdown() $resource = $resourceType = null; $data = $response->getPayload(); - if (!empty($data['payload'])) { + if (! empty($data['payload'])) { $pattern = $route->getLabel('cache.resource', null); - if (!empty($pattern)) { + if (! empty($pattern)) { $resource = $parseLabel($pattern, $responsePayload, $requestParams, $user); } $pattern = $route->getLabel('cache.resourceType', null); - if (!empty($pattern)) { + if (! empty($pattern)) { $resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user); } - $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; + $key = md5($request->getURI().implode('*', $request->getParams())).'*'.APP_CACHE_BUSTER; $data = json_encode([ 'resourceType' => $resourceType, 'resource' => $resource, 'contentType' => $response->getContentType(), 'payload' => base64_encode($data['payload']), - ]) ; + ]); $signature = md5($data); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); $now = DateTime::now(); if ($cacheLog->isEmpty()) { Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ - '$id' => $key, - 'resource' => $resource, - 'accessedAt' => $now, - 'signature' => $signature, + '$id' => $key, + 'resource' => $resource, + 'accessedAt' => $now, + 'signature' => $signature, ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); @@ -576,20 +571,18 @@ App::shutdown() if ($signature !== $cacheLog->getAttribute('signature')) { $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) + new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$project->getId()) ); $cache->save($key, $data); } } } - - if ($project->getId() !== 'console') { if ($mode !== APP_MODE_ADMIN) { $fileSize = 0; $file = $request->getFiles('file'); - if (!empty($file)) { + if (! empty($file)) { $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } @@ -607,7 +600,7 @@ App::shutdown() /** * Update user last activity */ - if (!$user->isEmpty()) { + if (! $user->isEmpty()) { $accessedAt = $user->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCCESS)) > $accessedAt) { $user->setAttribute('accessedAt', DateTime::now()); diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index 5b1af0d36c..acb8410804 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -1,9 +1,9 @@ inject('request') ->inject('project') ->action(function (App $utopia, Request $request, Document $project) { - $route = $utopia->match($request); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index dcf9c80a51..37914dda37 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -11,9 +11,9 @@ App::init() ->action(function (Request $request, Response $response) { $response ->addHeader('X-Frame-Options', 'SAMEORIGIN') // Avoid console and homepage from showing in iframes - ->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url=' . \urlencode($request->getURI())) + ->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url='.\urlencode($request->getURI())) ->addHeader('X-UA-Compatible', 'IE=Edge') // Deny IE browsers from going into quirks mode - ; +; }); App::get('/console/*') @@ -30,41 +30,41 @@ App::get('/console/*') ->inject('request') ->inject('response') ->action(function (Request $request, Response $response) { - $fallback = file_get_contents(__DIR__ . '/../../../console/index.html'); + $fallback = file_get_contents(__DIR__.'/../../../console/index.html'); // Card SSR if (\str_starts_with($request->getURI(), '/card')) { $urlCunks = \explode('/', $request->getURI()); $userId = $urlCunks[\count($urlCunks) - 1] ?? ''; - $domain = $request->getProtocol() . '://' . $request->getHostname(); + $domain = $request->getProtocol().'://'.$request->getHostname(); - if (!empty($userId)) { - $ogImageUrl = $domain . '/v1/cards/cloud-og?userId=' . $userId; + if (! empty($userId)) { + $ogImageUrl = $domain.'/v1/cards/cloud-og?userId='.$userId; } else { - $ogImageUrl = $domain . '/v1/cards/cloud-og?mock=normal'; + $ogImageUrl = $domain.'/v1/cards/cloud-og?mock=normal'; } $ogTags = [ 'Appwrite Cloud Card', '', - '', + '', '', '', '', '', '', '', - '', + '', '', - '', - '', + '', + '', '', '', '', '', '', - '', + '', ]; $fallback = \str_replace('', \implode('', $ogTags), $fallback); diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index e90f3ec25b..fb33350792 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -24,14 +24,14 @@ App::get('/versions') continue; } - if (isset($language['enabled']) && !$language['enabled']) { + if (isset($language['enabled']) && ! $language['enabled']) { continue; } $platformKey = $platform['key'] ?? ''; $languageKey = $language['key'] ?? ''; $version = $language['version'] ?? ''; - $versions[$platformKey . '-' . $languageKey] = $version; + $versions[$platformKey.'-'.$languageKey] = $version; } } diff --git a/app/http.php b/app/http.php index 8ce7b6f017..88ee35ff1f 100644 --- a/app/http.php +++ b/app/http.php @@ -1,30 +1,30 @@ on('WorkerStart', function ($server, $workerId) { - Console::success('Worker ' . ++$workerId . ' started successfully'); + Console::success('Worker '.++$workerId.' started successfully'); }); $http->on('BeforeReload', function ($server, $workerId) { @@ -53,16 +53,16 @@ $http->on('AfterReload', function ($server, $workerId) { Console::success('Reload completed...'); }); -Files::load(__DIR__ . '/../console'); +Files::load(__DIR__.'/../console'); -include __DIR__ . '/controllers/general.php'; +include __DIR__.'/controllers/general.php'; $http->on('start', function (Server $http) use ($payloadSize, $register) { $app = new App('UTC'); go(function () use ($register, $app) { $pools = $register->get('pools'); /** @var Group $pools */ - App::setResource('pools', fn() => $pools); + App::setResource('pools', fn () => $pools); // wait for database to be ready $attempts = 0; @@ -77,7 +77,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { } catch (\Exception $e) { Console::warning("Database not ready. Retrying connection ({$attempts})..."); if ($attempts >= $max) { - throw new \Exception('Failed to connect to database: ' . $e->getMessage()); + throw new \Exception('Failed to connect to database: '.$e->getMessage()); } sleep($sleep); } @@ -98,7 +98,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { } if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) { - $adapter = new TimeLimit("", 0, 1, $dbForConsole); + $adapter = new TimeLimit('', 0, 1, $dbForConsole); $adapter->setup(); } @@ -109,11 +109,11 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { if (($collection['$collection'] ?? '') !== Database::METADATA) { continue; } - if (!$dbForConsole->getCollection($key)->isEmpty()) { + if (! $dbForConsole->getCollection($key)->isEmpty()) { continue; } - Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...'); + Console::success('[Setup] - Creating collection: '.$collection['$id'].'...'); $attributes = []; $indexes = []; @@ -128,7 +128,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' + 'format' => $attribute['format'] ?? '', ]); } @@ -145,7 +145,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { $dbForConsole->createCollection($key, $attributes, $indexes); } - if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) { + if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && ! $dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) { Console::success('[Setup] - Creating default bucket...'); $dbForConsole->createDocument('buckets', new Document([ '$id' => ID::custom('default'), @@ -188,7 +188,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' + 'format' => $attribute['format'] ?? '', ]); } @@ -202,7 +202,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { ]); } - $dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); + $dbForConsole->createCollection('bucket_'.$bucket->getInternalId(), $attributes, $indexes); } $pools->reclaim(); @@ -210,7 +210,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { Console::success('[Setup] - Server database init completed...'); }); - Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)'); + Console::success('Server started successfully (max payload is '.number_format($payloadSize).' bytes)'); Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}"); // listen ctrl + c @@ -229,8 +229,8 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $response ->setContentType(Files::getFileMimeType($request->getURI())) - ->addHeader('Cache-Control', 'public, max-age=' . $time) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache + ->addHeader('Cache-Control', 'public, max-age='.$time) + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache ->send(Files::getFileContents($request->getURI())); return; @@ -239,7 +239,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $app = new App('UTC'); $pools = $register->get('pools'); - App::setResource('pools', fn() => $pools); + App::setResource('pools', fn () => $pools); try { Authorization::cleanRoles(); @@ -249,7 +249,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } catch (\Throwable $th) { $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); - $logger = $app->getResource("logger"); + $logger = $app->getResource('logger'); if ($logger) { try { /** @var Utopia\Database\Document $user */ @@ -258,16 +258,16 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo // All good, user is optional information for logger } - $loggerBreadcrumbs = $app->getResource("loggerBreadcrumbs"); + $loggerBreadcrumbs = $app->getResource('loggerBreadcrumbs'); $route = $app->match($request); $log = new Utopia\Logger\Log(); - if (isset($user) && !$user->isEmpty()) { + if (isset($user) && ! $user->isEmpty()) { $log->setUser(new User($user->getId())); } - $log->setNamespace("http"); + $log->setNamespace('http'); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); @@ -279,7 +279,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log->addTag('code', $th->getCode()); // $log->addTag('projectId', $project->getId()); // TODO: Figure out how to get ProjectID, if it becomes relevant $log->addTag('hostname', $request->getHostname()); - $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); + $log->addTag('locale', (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); @@ -287,7 +287,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log->addExtra('detailedTrace', $th->getTrace()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); + $action = $route->getLabel('sdk.namespace', 'UNKNOWN_NAMESPACE').'.'.$route->getLabel('sdk.method', 'UNKNOWN_METHOD'); $log->setAction($action); $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; @@ -298,18 +298,18 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } $responseCode = $logger->addLog($log); - Console::info('Log pushed with status code: ' . $responseCode); + Console::info('Log pushed with status code: '.$responseCode); } - Console::error('[Error] Type: ' . get_class($th)); - Console::error('[Error] Message: ' . $th->getMessage()); - Console::error('[Error] File: ' . $th->getFile()); - Console::error('[Error] Line: ' . $th->getLine()); + Console::error('[Error] Type: '.get_class($th)); + Console::error('[Error] Message: '.$th->getMessage()); + Console::error('[Error] File: '.$th->getFile()); + Console::error('[Error] Line: '.$th->getLine()); $swooleResponse->setStatusCode(500); $output = ((App::isDevelopment())) ? [ - 'message' => 'Error: ' . $th->getMessage(), + 'message' => 'Error: '.$th->getMessage(), 'code' => 500, 'file' => $th->getFile(), 'line' => $th->getLine(), diff --git a/app/init.php b/app/init.php index ea3a039ec9..2eb066e737 100644 --- a/app/init.php +++ b/app/init.php @@ -5,11 +5,9 @@ * * Initializes both Appwrite API entry point, queue workers, and CLI tasks. * Set configuration, framework resources & app constants - * */ - -if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { - require_once __DIR__ . '/../vendor/autoload.php'; +if (\file_exists(__DIR__.'/../vendor/autoload.php')) { + require_once __DIR__.'/../vendor/autoload.php'; } ini_set('memory_limit', '512M'); @@ -18,41 +16,54 @@ ini_set('display_startup_errors', 1); ini_set('default_socket_timeout', -1); error_reporting(E_ALL); -use Appwrite\Event\Usage; -use Appwrite\Extend\Exception; +use Ahc\Jwt\JWT; +use Ahc\Jwt\JWTException; use Appwrite\Auth\Auth; use Appwrite\Event\Audit; use Appwrite\Event\Database as EventDatabase; +use Appwrite\Event\Delete; use Appwrite\Event\Event; +use Appwrite\Event\Func; use Appwrite\Event\Mail; use Appwrite\Event\Phone; -use Appwrite\Event\Delete; +use Appwrite\Event\Usage; +use Appwrite\Extend\Exception; +use Appwrite\GraphQL\Promises\Adapter\Swoole; use Appwrite\GraphQL\Schema; use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Origin; use Appwrite\OpenSSL\OpenSSL; use Appwrite\URL\URL as AppwriteURL; +use MaxMind\Db\Reader; +use PHPMailer\PHPMailer\PHPMailer; +use Swoole\Database\PDOProxy; use Utopia\App; -use Utopia\Logger\Logger; use Utopia\Cache\Adapter\Redis as RedisCache; +use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\Config\Config; -use Utopia\Database\Helpers\ID; +use Utopia\Database\Adapter\MariaDB; +use Utopia\Database\Adapter\MySQL; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Structure; -use Utopia\Locale\Locale; use Utopia\DSN\DSN; +use Utopia\Locale\Locale; +use Utopia\Logger\Logger; use Utopia\Messaging\Adapters\SMS\Mock; -use Appwrite\GraphQL\Promises\Adapter\Swoole; use Utopia\Messaging\Adapters\SMS\Msg91; use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; use Utopia\Messaging\Adapters\SMS\Twilio; use Utopia\Messaging\Adapters\SMS\Vonage; +use Utopia\Pools\Group; +use Utopia\Pools\Pool; +use Utopia\Queue; +use Utopia\Queue\Connection; use Utopia\Registry\Registry; use Utopia\Storage\Device; use Utopia\Storage\Device\Backblaze; @@ -61,22 +72,9 @@ use Utopia\Storage\Device\Linode; use Utopia\Storage\Device\Local; use Utopia\Storage\Device\S3; use Utopia\Storage\Device\Wasabi; -use Utopia\Cache\Adapter\Sharding; -use Utopia\Database\Adapter\MariaDB; -use Utopia\Database\Adapter\MySQL; -use Utopia\Pools\Group; -use Utopia\Pools\Pool; -use Ahc\Jwt\JWT; -use Ahc\Jwt\JWTException; -use Appwrite\Event\Func; -use MaxMind\Db\Reader; -use PHPMailer\PHPMailer\PHPMailer; -use Swoole\Database\PDOProxy; -use Utopia\Queue; -use Utopia\Queue\Connection; use Utopia\Storage\Storage; -use Utopia\Validator\Range; use Utopia\Validator\IP; +use Utopia\Validator\Range; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; @@ -84,7 +82,7 @@ const APP_NAME = 'Appwrite'; const APP_DOMAIN = 'appwrite.io'; const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address const APP_EMAIL_SECURITY = ''; // Default security email address -const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s'; +const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s'; const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; @@ -162,7 +160,7 @@ const DELETE_TYPE_REALTIME = 'realtime'; const DELETE_TYPE_BUCKETS = 'buckets'; const DELETE_TYPE_SESSIONS = 'sessions'; const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp'; -const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; +const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; const DELETE_TYPE_SCHEDULES = 'schedules'; // Compression type const COMPRESSION_TYPE_NONE = 'none'; @@ -184,7 +182,7 @@ const MAX_OUTPUT_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; -const METRIC_SESSIONS = 'sessions'; +const METRIC_SESSIONS = 'sessions'; const METRIC_DATABASES = 'databases'; const METRIC_COLLECTIONS = 'collections'; const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections'; @@ -192,28 +190,28 @@ const METRIC_DOCUMENTS = 'documents'; const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; const METRIC_BUCKETS = 'buckets'; -const METRIC_FILES = 'files'; -const METRIC_FILES_STORAGE = 'files.storage'; +const METRIC_FILES = 'files'; +const METRIC_FILES_STORAGE = 'files.storage'; const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files'; -const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; -const METRIC_FUNCTIONS = 'functions'; -const METRIC_DEPLOYMENTS = 'deployments'; -const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; -const METRIC_BUILDS = 'builds'; -const METRIC_BUILDS_STORAGE = 'builds.storage'; -const METRIC_BUILDS_COMPUTE = 'builds.compute'; -const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; +const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; +const METRIC_FUNCTIONS = 'functions'; +const METRIC_DEPLOYMENTS = 'deployments'; +const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; +const METRIC_BUILDS = 'builds'; +const METRIC_BUILDS_STORAGE = 'builds.storage'; +const METRIC_BUILDS_COMPUTE = 'builds.compute'; +const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; -const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; -const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; -const METRIC_EXECUTIONS = 'executions'; -const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; -const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; -const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; -const METRIC_NETWORK_REQUESTS = 'network.requests'; -const METRIC_NETWORK_INBOUND = 'network.inbound'; -const METRIC_NETWORK_OUTBOUND = 'network.outbound'; +const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; +const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; +const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; +const METRIC_EXECUTIONS = 'executions'; +const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; +const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; +const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; +const METRIC_NETWORK_REQUESTS = 'network.requests'; +const METRIC_NETWORK_INBOUND = 'network.inbound'; +const METRIC_NETWORK_OUTBOUND = 'network.outbound'; $register = new Registry(); @@ -222,42 +220,42 @@ App::setMode(App::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION)); /* * ENV vars */ -Config::load('events', __DIR__ . '/config/events.php'); -Config::load('auth', __DIR__ . '/config/auth.php'); -Config::load('errors', __DIR__ . '/config/errors.php'); -Config::load('authProviders', __DIR__ . '/config/authProviders.php'); -Config::load('platforms', __DIR__ . '/config/platforms.php'); -Config::load('collections', __DIR__ . '/config/collections.php'); -Config::load('runtimes', __DIR__ . '/config/runtimes.php'); -Config::load('usage', __DIR__ . '/config/usage.php'); -Config::load('roles', __DIR__ . '/config/roles.php'); // User roles and scopes -Config::load('scopes', __DIR__ . '/config/scopes.php'); // User roles and scopes -Config::load('services', __DIR__ . '/config/services.php'); // List of services -Config::load('variables', __DIR__ . '/config/variables.php'); // List of env variables -Config::load('regions', __DIR__ . '/config/regions.php'); // List of available regions -Config::load('avatar-browsers', __DIR__ . '/config/avatars/browsers.php'); -Config::load('avatar-credit-cards', __DIR__ . '/config/avatars/credit-cards.php'); -Config::load('avatar-flags', __DIR__ . '/config/avatars/flags.php'); -Config::load('locale-codes', __DIR__ . '/config/locale/codes.php'); -Config::load('locale-currencies', __DIR__ . '/config/locale/currencies.php'); -Config::load('locale-eu', __DIR__ . '/config/locale/eu.php'); -Config::load('locale-languages', __DIR__ . '/config/locale/languages.php'); -Config::load('locale-phones', __DIR__ . '/config/locale/phones.php'); -Config::load('locale-countries', __DIR__ . '/config/locale/countries.php'); -Config::load('locale-continents', __DIR__ . '/config/locale/continents.php'); -Config::load('locale-templates', __DIR__ . '/config/locale/templates.php'); -Config::load('storage-logos', __DIR__ . '/config/storage/logos.php'); -Config::load('storage-mimes', __DIR__ . '/config/storage/mimes.php'); -Config::load('storage-inputs', __DIR__ . '/config/storage/inputs.php'); -Config::load('storage-outputs', __DIR__ . '/config/storage/outputs.php'); -Config::load('messagingProviders', __DIR__ . '/config/messagingProviders.php'); +Config::load('events', __DIR__.'/config/events.php'); +Config::load('auth', __DIR__.'/config/auth.php'); +Config::load('errors', __DIR__.'/config/errors.php'); +Config::load('authProviders', __DIR__.'/config/authProviders.php'); +Config::load('platforms', __DIR__.'/config/platforms.php'); +Config::load('collections', __DIR__.'/config/collections.php'); +Config::load('runtimes', __DIR__.'/config/runtimes.php'); +Config::load('usage', __DIR__.'/config/usage.php'); +Config::load('roles', __DIR__.'/config/roles.php'); // User roles and scopes +Config::load('scopes', __DIR__.'/config/scopes.php'); // User roles and scopes +Config::load('services', __DIR__.'/config/services.php'); // List of services +Config::load('variables', __DIR__.'/config/variables.php'); // List of env variables +Config::load('regions', __DIR__.'/config/regions.php'); // List of available regions +Config::load('avatar-browsers', __DIR__.'/config/avatars/browsers.php'); +Config::load('avatar-credit-cards', __DIR__.'/config/avatars/credit-cards.php'); +Config::load('avatar-flags', __DIR__.'/config/avatars/flags.php'); +Config::load('locale-codes', __DIR__.'/config/locale/codes.php'); +Config::load('locale-currencies', __DIR__.'/config/locale/currencies.php'); +Config::load('locale-eu', __DIR__.'/config/locale/eu.php'); +Config::load('locale-languages', __DIR__.'/config/locale/languages.php'); +Config::load('locale-phones', __DIR__.'/config/locale/phones.php'); +Config::load('locale-countries', __DIR__.'/config/locale/countries.php'); +Config::load('locale-continents', __DIR__.'/config/locale/continents.php'); +Config::load('locale-templates', __DIR__.'/config/locale/templates.php'); +Config::load('storage-logos', __DIR__.'/config/storage/logos.php'); +Config::load('storage-mimes', __DIR__.'/config/storage/mimes.php'); +Config::load('storage-inputs', __DIR__.'/config/storage/inputs.php'); +Config::load('storage-outputs', __DIR__.'/config/storage/outputs.php'); +Config::load('messagingProviders', __DIR__.'/config/messagingProviders.php'); $user = App::getEnv('_APP_REDIS_USER', ''); $pass = App::getEnv('_APP_REDIS_PASS', ''); -if (!empty($user) || !empty($pass)) { - Resque::setBackend('redis://' . $user . ':' . $pass . '@' . App::getEnv('_APP_REDIS_HOST', '') . ':' . App::getEnv('_APP_REDIS_PORT', '')); +if (! empty($user) || ! empty($pass)) { + Resque::setBackend('redis://'.$user.':'.$pass.'@'.App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', '')); } else { - Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '') . ':' . App::getEnv('_APP_REDIS_PORT', '')); + Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', '')); } /** @@ -313,8 +311,7 @@ Database::addFilter( if (isset($formatOptions['min']) || isset($formatOptions['max'])) { $attribute ->setAttribute('min', $formatOptions['min']) - ->setAttribute('max', $formatOptions['max']) - ; + ->setAttribute('max', $formatOptions['max']); } return $value; @@ -437,7 +434,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn() => $database + return Authorization::skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -451,7 +448,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn() => $database + return Authorization::skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -493,7 +490,7 @@ Database::addFilter( return null; } $value = json_decode($value, true); - $key = App::getEnv('_APP_OPENSSL_KEY_V' . $value['version']); + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$value['version']); return OpenSSL::decrypt($value['data'], $value['method'], $key, 0, hex2bin($value['iv']), hex2bin($value['tag'])); } @@ -506,11 +503,11 @@ Database::addFilter( $user->getId(), $user->getAttribute('email', ''), $user->getAttribute('name', ''), - $user->getAttribute('phone', '') + $user->getAttribute('phone', ''), ]; foreach ($user->getAttribute('labels', []) as $label) { - $searchValues[] = 'label:' . $label; + $searchValues[] = 'label:'.$label; } $search = implode(' ', \array_filter($searchValues)); @@ -528,7 +525,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn() => $database + return Authorization::skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -542,7 +539,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - $provider = Authorization::skip(fn() => $database + $provider = Authorization::skip(fn () => $database ->findOne('providers', [ Query::equal('$id', [$document->getAttribute('providerId')]), Query::select(['type']), @@ -551,6 +548,7 @@ Database::addFilter( if ($provider) { return $provider->getAttribute('type'); } + return null; } ); @@ -568,6 +566,7 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () { Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) { $elements = $attribute['formatOptions']['elements']; + return new WhiteList($elements, true); }, Database::VAR_STRING); @@ -582,12 +581,14 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () { Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) { $min = $attribute['formatOptions']['min'] ?? -INF; $max = $attribute['formatOptions']['max'] ?? INF; + return new Range($min, $max, Range::TYPE_INTEGER); }, Database::VAR_INTEGER); Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) { $min = $attribute['formatOptions']['min'] ?? -INF; $max = $attribute['formatOptions']['max'] ?? INF; + return new Range($min, $max, Range::TYPE_FLOAT); }, Database::VAR_FLOAT); @@ -603,12 +604,13 @@ $register->set('logger', function () { return null; } - if (!Logger::hasProvider($providerName)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); + if (! Logger::hasProvider($providerName)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Logging provider not supported. Logging is disabled'); } - $classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName); + $classname = '\\Utopia\\Logger\\Adapter\\'.\ucfirst($providerName); $adapter = new $classname($providerConfig); + return new Logger($adapter); }); $register->set('pools', function () { @@ -677,7 +679,7 @@ $register->set('pools', function () { throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500); } - $poolSize = (int)($instanceConnections / $workerCount); + $poolSize = (int) ($instanceConnections / $workerCount); foreach ($connections as $key => $connection) { $type = $connection['type'] ?? ''; @@ -688,7 +690,7 @@ $register->set('pools', function () { $dsns = explode(',', $connection['dsns'] ?? ''); foreach ($dsns as &$dsn) { $dsn = explode('=', $dsn); - $name = ($multipe) ? $key . '_' . $dsn[0] : $key; + $name = ($multipe) ? $key.'_'.$dsn[0] : $key; $dsn = $dsn[1] ?? ''; $config[] = $name; if (empty($dsn)) { @@ -704,8 +706,8 @@ $register->set('pools', function () { $dsnScheme = $dsn->getScheme(); $dsnDatabase = $dsn->getPath(); - if (!in_array($dsnScheme, $schemes)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); + if (! in_array($dsnScheme, $schemes)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid console database scheme'); } /** @@ -720,21 +722,21 @@ $register->set('pools', function () { case 'mariadb': $resource = function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array( + return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [ PDO::ATTR_TIMEOUT => 3, // Seconds PDO::ATTR_PERSISTENT => true, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed PDO::ATTR_EMULATE_PREPARES => true, - PDO::ATTR_STRINGIFY_FETCHES => true - )); + PDO::ATTR_STRINGIFY_FETCHES => true, + ]); }); }; break; case 'redis': $resource = function () use ($dsnHost, $dsnPort, $dsnPass) { $redis = new Redis(); - @$redis->pconnect($dsnHost, (int)$dsnPort); + @$redis->pconnect($dsnHost, (int) $dsnPort); if ($dsnPass) { $redis->auth($dsnPass); } @@ -745,7 +747,7 @@ $register->set('pools', function () { break; default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"); + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'); break; } @@ -779,7 +781,7 @@ $register->set('pools', function () { break; default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Server error: Missing adapter implementation.'); break; } @@ -789,7 +791,7 @@ $register->set('pools', function () { $group->add($pool); } - Config::setParam('pools-' . $key, $config); + Config::setParam('pools-'.$key, $config); } return $group; @@ -806,14 +808,14 @@ $register->set('smtp', function () { $mail->XMailer = 'Appwrite Mailer'; $mail->Host = App::getEnv('_APP_SMTP_HOST', 'smtp'); $mail->Port = App::getEnv('_APP_SMTP_PORT', 25); - $mail->SMTPAuth = (!empty($username) && !empty($password)); + $mail->SMTPAuth = (! empty($username) && ! empty($password)); $mail->Username = $username; $mail->Password = $password; $mail->SMTPSecure = App::getEnv('_APP_SMTP_SECURE', false); $mail->SMTPAutoTLS = false; $mail->CharSet = 'UTF-8'; - $from = \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); + $from = \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')); $email = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $mail->setFrom($email, $from); @@ -824,12 +826,13 @@ $register->set('smtp', function () { return $mail; }); $register->set('geodb', function () { - return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2023-01.mmdb'); + return new Reader(__DIR__.'/assets/dbip/dbip-country-lite-2023-01.mmdb'); }); $register->set('passwordsDictionary', function () { - $content = \file_get_contents(__DIR__ . '/assets/security/10k-common-passwords'); + $content = \file_get_contents(__DIR__.'/assets/security/10k-common-passwords'); $content = explode("\n", $content); $content = array_flip($content); + return $content; }); $register->set('promiseAdapter', function () { @@ -845,12 +848,12 @@ $locales = Config::getParam('locale-codes', []); foreach ($locales as $locale) { $code = $locale['code']; - $path = __DIR__ . '/config/locale/translations/' . $code . '.json'; + $path = __DIR__.'/config/locale/translations/'.$code.'.json'; - if (!\file_exists($path)) { - $path = __DIR__ . '/config/locale/translations/' . \substr($code, 0, 2) . '.json'; // if `ar-ae` doesn't exist, look for `ar` - if (!\file_exists($path)) { - $path = __DIR__ . '/config/locale/translations/en.json'; // if none translation exists, use default from `en.json` + if (! \file_exists($path)) { + $path = __DIR__.'/config/locale/translations/'.\substr($code, 0, 2).'.json'; // if `ar-ae` doesn't exist, look for `ar` + if (! \file_exists($path)) { + $path = __DIR__.'/config/locale/translations/en.json'; // if none translation exists, use default from `en.json` } } @@ -878,20 +881,20 @@ App::setResource('loggerBreadcrumbs', function () { return []; }); -App::setResource('register', fn() => $register); -App::setResource('locale', fn() => new Locale(App::getEnv('_APP_LOCALE', 'en'))); +App::setResource('register', fn () => $register); +App::setResource('locale', fn () => new Locale(App::getEnv('_APP_LOCALE', 'en'))); App::setResource('localeCodes', function () { - return array_map(fn($locale) => $locale['code'], Config::getParam('locale-codes', [])); + return array_map(fn ($locale) => $locale['code'], Config::getParam('locale-codes', [])); }); // Queues -App::setResource('events', fn() => new Event('', '')); -App::setResource('audits', fn() => new Audit()); -App::setResource('mails', fn() => new Mail()); -App::setResource('deletes', fn() => new Delete()); -App::setResource('database', fn() => new EventDatabase()); -App::setResource('messaging', fn() => new Phone()); +App::setResource('events', fn () => new Event('', '')); +App::setResource('audits', fn () => new Audit()); +App::setResource('mails', fn () => new Mail()); +App::setResource('deletes', fn () => new Delete()); +App::setResource('database', fn () => new EventDatabase()); +App::setResource('messaging', fn () => new Phone()); App::setResource('queue', function (Group $pools) { return $pools->get('queue')->pop()->getResource(); }, ['pools']); @@ -917,7 +920,7 @@ App::setResource('clients', function ($request, $console, $project) { fn ($node) => $node['hostname'], \array_filter( $console->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname'])) + fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && ! empty($node['hostname'])) ) ); @@ -928,7 +931,7 @@ App::setResource('clients', function ($request, $console, $project) { fn ($node) => $node['hostname'], \array_filter( $project->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname'])) + fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && ! empty($node['hostname'])) ) ) ) @@ -944,23 +947,22 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons /** @var Utopia\Database\Database $dbForProject */ /** @var Utopia\Database\Database $dbForConsole */ /** @var string $mode */ - Authorization::setDefaultStatus(true); - Auth::setCookieName('a_session_' . $project->getId()); + Auth::setCookieName('a_session_'.$project->getId()); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; if (APP_MODE_ADMIN === $mode) { - Auth::setCookieName('a_session_' . $console->getId()); + Auth::setCookieName('a_session_'.$console->getId()); $authDuration = Auth::TOKEN_EXPIRATION_LOGIN_LONG; } $session = Auth::decodeSession( $request->getCookie( Auth::$cookieName, // Get sessions - $request->getCookie(Auth::$cookieName . '_legacy', '') + $request->getCookie(Auth::$cookieName.'_legacy', '') ) - );// Get fallback session from old clients (no SameSite support) + ); // Get fallback session from old clients (no SameSite support) // Get fallback session from clients who block 3rd-party cookies if ($response) { @@ -991,7 +993,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons if ( $user->isEmpty() // Check a document has been found in the DB - || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) + || ! Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) ) { // Validate user has valid login token $user = new Document([]); } @@ -1006,13 +1008,13 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $authJWT = $request->getHeader('x-appwrite-jwt', ''); - if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication + if (! empty($authJWT) && ! $project->isEmpty()) { // JWT authentication $jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway. try { $payload = $jwt->decode($authJWT); } catch (JWTException $error) { - throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage()); + throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. '.$error->getMessage()); } $jwtUserId = $payload['userId'] ?? ''; @@ -1034,14 +1036,13 @@ App::setResource('project', function ($dbForConsole, $request, $console) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForConsole */ /** @var Utopia\Database\Document $console */ - $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); if (empty($projectId) || $projectId === 'console') { return $console; } - $project = Authorization::skip(fn() => $dbForConsole->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); return $project; }, ['dbForConsole', 'request', 'console']); @@ -1076,12 +1077,12 @@ App::setResource('console', function () { 'limit' => (App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds ], - 'authWhitelistEmails' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], - 'authWhitelistIPs' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], + 'authWhitelistEmails' => (! empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], + 'authWhitelistIPs' => (! empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], 'authProviders' => [ 'githubEnabled' => true, 'githubSecret' => App::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''), - 'githubAppid' => App::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '') + 'githubAppid' => App::getEnv('_APP_CONSOLE_GITHUB_APP_ID', ''), ], ]); }, []); @@ -1094,11 +1095,10 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, $dbAdapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, $cache); - $database->setNamespace('_' . $project->getInternalId()); + $database->setNamespace('_'.$project->getInternalId()); return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); @@ -1107,8 +1107,7 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) { $dbAdapter = $pools ->get('console') ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, $cache); @@ -1125,8 +1124,7 @@ App::setResource('cache', function (Group $pools) { $adapters[] = $pools ->get($value) ->pop() - ->getResource() - ; + ->getResource(); } return new Cache(new Sharding($adapters)); @@ -1137,15 +1135,15 @@ App::setResource('deviceLocal', function () { }); App::setResource('deviceFiles', function ($project) { - return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); + return getDevice(APP_STORAGE_UPLOADS.'/app-'.$project->getId()); }, ['project']); App::setResource('deviceFunctions', function ($project) { - return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); + return getDevice(APP_STORAGE_FUNCTIONS.'/app-'.$project->getId()); }, ['project']); App::setResource('deviceBuilds', function ($project) { - return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); + return getDevice(APP_STORAGE_BUILDS.'/app-'.$project->getId()); }, ['project']); function getDevice($root): Device @@ -1167,7 +1165,7 @@ function getDevice($root): Device $bucket = $dsn->getPath(); $region = $dsn->getParam('region'); } catch (\Exception $e) { - Console::error($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); + Console::error($e->getMessage().'Invalid DSN. Defaulting to Local device.'); } switch ($device) { @@ -1240,7 +1238,6 @@ App::setResource('promiseAdapter', function ($register) { }, ['register']); App::setResource('schema', function ($utopia, $dbForProject) { - $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); $query = Query::getByType($queries, [Query::TYPE_LIMIT])[0] ?? null; @@ -1250,7 +1247,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { }; $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn() => $dbForProject->find('attributes', [ + $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -1280,7 +1277,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { $params = [ 'list' => function (string $databaseId, string $collectionId, array $args) { - return [ 'queries' => $args['queries']]; + return ['queries' => $args['queries']]; }, 'create' => function (string $databaseId, string $collectionId, array $args) { $id = $args['id'] ?? 'unique()'; @@ -1328,18 +1325,21 @@ App::setResource('schema', function ($utopia, $dbForProject) { App::setResource('contributors', function () { $path = 'app/config/cloud/contributors.json'; $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; + return $list; }, []); App::setResource('employees', function () { $path = 'app/config/cloud/employees.json'; $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; + return $list; }, []); App::setResource('heroes', function () { $path = 'app/config/cloud/heroes.json'; $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; + return $list; }, []); @@ -1347,12 +1347,13 @@ App::setResource('requestTimestamp', function ($request) { //TODO: Move this to the Request class itself $timestampHeader = $request->getHeader('x-appwrite-timestamp'); $requestTimestamp = null; - if (!empty($timestampHeader)) { + if (! empty($timestampHeader)) { try { $requestTimestamp = new \DateTime($timestampHeader); } catch (\Throwable $e) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid X-Appwrite-Timestamp header value'); } } + return $requestTimestamp; }, ['request']); diff --git a/app/preload.php b/app/preload.php index e587bfaed5..cec44d4a7d 100644 --- a/app/preload.php +++ b/app/preload.php @@ -5,38 +5,36 @@ * * Inializes both Appwrite API entry point, queue workers, and CLI tasks. * Set configuration, framework resources, app constants - * */ - ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); -if (file_exists(__DIR__ . '/../vendor/autoload.php')) { - require __DIR__ . '/../vendor/autoload.php'; +if (file_exists(__DIR__.'/../vendor/autoload.php')) { + require __DIR__.'/../vendor/autoload.php'; } use Utopia\Preloader\Preloader; -include __DIR__ . '/controllers/general.php'; +include __DIR__.'/controllers/general.php'; $preloader = new Preloader(); foreach ( [ - realpath(__DIR__ . '/../vendor/composer'), - realpath(__DIR__ . '/../vendor/amphp'), - realpath(__DIR__ . '/../vendor/felixfbecker'), - realpath(__DIR__ . '/../vendor/twig/twig'), - realpath(__DIR__ . '/../vendor/guzzlehttp/guzzle'), - realpath(__DIR__ . '/../vendor/slickdeals'), - realpath(__DIR__ . '/../vendor/psr/log'), - realpath(__DIR__ . '/../vendor/matomo'), - realpath(__DIR__ . '/../vendor/symfony'), - realpath(__DIR__ . '/../vendor/mongodb'), - realpath(__DIR__ . '/../vendor/utopia-php/websocket'), // TODO: remove workerman autoload - realpath(__DIR__ . '/../vendor/utopia-php/cache'), // TODO: remove memcached autoload - realpath(__DIR__ . '/../vendor/utopia-php/queue/src/Queue/Adapter/Workerman.php'), // TODO: remove workerman autoload + realpath(__DIR__.'/../vendor/composer'), + realpath(__DIR__.'/../vendor/amphp'), + realpath(__DIR__.'/../vendor/felixfbecker'), + realpath(__DIR__.'/../vendor/twig/twig'), + realpath(__DIR__.'/../vendor/guzzlehttp/guzzle'), + realpath(__DIR__.'/../vendor/slickdeals'), + realpath(__DIR__.'/../vendor/psr/log'), + realpath(__DIR__.'/../vendor/matomo'), + realpath(__DIR__.'/../vendor/symfony'), + realpath(__DIR__.'/../vendor/mongodb'), + realpath(__DIR__.'/../vendor/utopia-php/websocket'), // TODO: remove workerman autoload + realpath(__DIR__.'/../vendor/utopia-php/cache'), // TODO: remove memcached autoload + realpath(__DIR__.'/../vendor/utopia-php/queue/src/Queue/Adapter/Workerman.php'), // TODO: remove workerman autoload ] as $key => $value ) { if ($value !== false) { @@ -45,7 +43,7 @@ foreach ( } $preloader - ->paths(realpath(__DIR__ . '/../app/config')) - ->paths(realpath(__DIR__ . '/../app/controllers')) - ->paths(realpath(__DIR__ . '/../src')) + ->paths(realpath(__DIR__.'/../app/config')) + ->paths(realpath(__DIR__.'/../app/controllers')) + ->paths(realpath(__DIR__.'/../src')) ->load(); diff --git a/app/realtime.php b/app/realtime.php index 772eee49d6..24def0ec61 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -3,6 +3,7 @@ use Appwrite\Auth\Auth; use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Network\Validator\Origin; +use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; @@ -12,23 +13,22 @@ use Swoole\Timer; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; -use Utopia\CLI\Console; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Role; -use Utopia\Logger\Log; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Appwrite\Utopia\Request; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; +use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\WebSocket\Server; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Logger\Log; use Utopia\WebSocket\Adapter; +use Utopia\WebSocket\Server; -require_once __DIR__ . '/init.php'; +require_once __DIR__.'/init.php'; Runtime::enableCoroutine(SWOOLE_HOOK_ALL); @@ -42,8 +42,7 @@ function getConsoleDB(): Database $dbAdapter = $pools ->get('console') ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, getCache()); @@ -66,11 +65,10 @@ function getProjectDB(Document $project): Database $dbAdapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, getCache()); - $database->setNamespace('_' . $project->getInternalId()); + $database->setNamespace('_'.$project->getInternalId()); return $database; } @@ -80,7 +78,6 @@ function getCache(): Cache global $register; $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ - $list = Config::getParam('pools-cache', []); $adapters = []; @@ -88,8 +85,7 @@ function getCache(): Cache $adapters[] = $pools ->get($value) ->pop() - ->getResource() - ; + ->getResource(); } return new Cache(new Sharding($adapters)); @@ -126,7 +122,7 @@ $logError = function (Throwable $error, string $action) use ($register) { $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $log = new Log(); - $log->setNamespace("realtime"); + $log->setNamespace('realtime'); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); @@ -146,13 +142,13 @@ $logError = function (Throwable $error, string $action) use ($register) { $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('Realtime log pushed with status code: ' . $responseCode); + Console::info('Realtime log pushed with status code: '.$responseCode); } - Console::error('[Error] Type: ' . get_class($error)); - Console::error('[Error] Message: ' . $error->getMessage()); - Console::error('[Error] File: ' . $error->getFile()); - Console::error('[Error] Line: ' . $error->getLine()); + Console::error('[Error] Type: '.get_class($error)); + Console::error('[Error] Message: '.$error->getMessage()); + Console::error('[Error] File: '.$error->getFile()); + Console::error('[Error] Line: '.$error->getLine()); }; $server->error($logError); @@ -177,7 +173,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume '$permissions' => [], 'container' => $containerId, 'timestamp' => DateTime::now(), - 'value' => '{}' + 'value' => '{}', ]); $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); @@ -211,7 +207,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (\Throwable $th) { - call_user_func($logError, $th, "updateWorkerDocument"); + call_user_func($logError, $th, 'updateWorkerDocument'); } finally { $register->get('pools')->reclaim(); } @@ -219,12 +215,12 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume }); $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime, $logError) { - Console::success('Worker ' . $workerId . ' started successfully'); + Console::success('Worker '.$workerId.' started successfully'); $attempts = 0; $start = time(); - Timer::tick(5000, function () use ($server, $register, $realtime, $stats, $logError) { + Timer::tick(5000, function () use ($server, $register, $realtime, $stats) { /** * Sending current connections to project channels on the console project every 5 seconds. */ @@ -243,34 +239,34 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, foreach ($list as $document) { foreach (json_decode($document->getAttribute('value')) as $projectId => $value) { if (array_key_exists($projectId, $payload)) { - $payload[$projectId] += $value; + $payload[$projectId] += $value; } else { - $payload[$projectId] = $value; + $payload[$projectId] = $value; } } } foreach ($stats as $projectId => $value) { - if (!array_key_exists($projectId, $payload)) { + if (! array_key_exists($projectId, $payload)) { continue; } $event = [ 'project' => 'console', - 'roles' => ['team:' . $stats->get($projectId, 'teamId')], + 'roles' => ['team:'.$stats->get($projectId, 'teamId')], 'data' => [ 'events' => ['stats.connections'], 'channels' => ['project'], 'timestamp' => DateTime::formatTz(DateTime::now()), 'payload' => [ - $projectId => $payload[$projectId] - ] - ] + $projectId => $payload[$projectId], + ], + ], ]; $server->send($realtime->getSubscribers($event), json_encode([ 'type' => 'event', - 'data' => $event['data'] + 'data' => $event['data'], ])); } @@ -289,13 +285,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, 'events' => ['test.event'], 'channels' => ['tests'], 'timestamp' => DateTime::formatTz(DateTime::now()), - 'payload' => $payload - ] + 'payload' => $payload, + ], ]; $server->send($realtime->getSubscribers($event), json_encode([ 'type' => 'event', - 'data' => $event['data'] + 'data' => $event['data'], ])); } }); @@ -303,8 +299,8 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, while ($attempts < 300) { try { if ($attempts > 0) { - Console::error('Pub/sub connection lost (lasted ' . (time() - $start) . ' seconds, worker: ' . $workerId . '). - Attempting restart in 5 seconds (attempt #' . $attempts . ')'); + Console::error('Pub/sub connection lost (lasted '.(time() - $start).' seconds, worker: '.$workerId.'). + Attempting restart in 5 seconds (attempt #'.$attempts.')'); sleep(5); // 5 sec delay between connection attempts } $start = time(); @@ -314,9 +310,9 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, if ($redis->ping(true)) { $attempts = 0; - Console::success('Pub/sub connection established (worker: ' . $workerId . ')'); + Console::success('Pub/sub connection established (worker: '.$workerId.')'); } else { - Console::error('Pub/sub failed (worker: ' . $workerId . ')'); + Console::error('Pub/sub failed (worker: '.$workerId.')'); } $redis->subscribe(['realtime'], function (Redis $redis, string $channel, string $payload) use ($server, $workerId, $stats, $register, $realtime) { @@ -326,10 +322,10 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $projectId = $event['project']; $userId = $event['userId']; - if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) { - $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId])); + if ($realtime->hasSubscriber($projectId, 'user:'.$userId)) { + $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:'.$userId])); $consoleDatabase = getConsoleDB(); - $project = Authorization::skip(fn() => $consoleDatabase->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); $user = $database->getDocument('users', $userId); @@ -344,17 +340,17 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $receivers = $realtime->getSubscribers($event); - if (App::isDevelopment() && !empty($receivers)) { - Console::log("[Debug][Worker {$workerId}] Receivers: " . count($receivers)); - Console::log("[Debug][Worker {$workerId}] Receivers Connection IDs: " . json_encode($receivers)); - Console::log("[Debug][Worker {$workerId}] Event: " . $payload); + if (App::isDevelopment() && ! empty($receivers)) { + Console::log("[Debug][Worker {$workerId}] Receivers: ".count($receivers)); + Console::log("[Debug][Worker {$workerId}] Receivers Connection IDs: ".json_encode($receivers)); + Console::log("[Debug][Worker {$workerId}] Event: ".$payload); } $server->send( $receivers, json_encode([ 'type' => 'event', - 'data' => $event['data'] + 'data' => $event['data'], ]) ); @@ -363,11 +359,12 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, } }); } catch (\Throwable $th) { - call_user_func($logError, $th, "pubSubConnection"); + call_user_func($logError, $th, 'pubSubConnection'); - Console::error('Pub/sub error: ' . $th->getMessage()); + Console::error('Pub/sub error: '.$th->getMessage()); $attempts++; sleep(DATABASE_RECONNECT_SLEEP); + continue; } finally { $register->get('pools')->reclaim(); @@ -384,9 +381,9 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, Console::info("Connection open (user: {$connection})"); - App::setResource('pools', fn() => $register->get('pools')); - App::setResource('request', fn() => $request); - App::setResource('response', fn() => $response); + App::setResource('pools', fn () => $register->get('pools')); + App::setResource('request', fn () => $request); + App::setResource('response', fn () => $response); try { /** @var \Utopia\Database\Document $project */ @@ -427,7 +424,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $origin = $request->getOrigin(); $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); - if (!$originValidator->isValid($origin) && $project->getId() !== 'console') { + if (! $originValidator->isValid($origin) && $project->getId() !== 'console') { throw new Exception($originValidator->getDescription(), 1008); } @@ -450,25 +447,25 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, 'type' => 'connected', 'data' => [ 'channels' => array_keys($channels), - 'user' => $user - ] + 'user' => $user, + ], ])); $stats->set($project->getId(), [ 'projectId' => $project->getId(), - 'teamId' => $project->getAttribute('teamId') + 'teamId' => $project->getAttribute('teamId'), ]); $stats->incr($project->getId(), 'connections'); $stats->incr($project->getId(), 'connectionsTotal'); } catch (\Throwable $th) { - call_user_func($logError, $th, "initServer"); + call_user_func($logError, $th, 'initServer'); $response = [ 'type' => 'error', 'data' => [ 'code' => $th->getCode(), - 'message' => $th->getMessage() - ] + 'message' => $th->getMessage(), + ], ]; $server->send([$connection], json_encode($response)); @@ -476,8 +473,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if (App::isDevelopment()) { Console::error('[Error] Connection Error'); - Console::error('[Error] Code: ' . $response['data']['code']); - Console::error('[Error] Message: ' . $response['data']['message']); + Console::error('[Error] Code: '.$response['data']['code']); + Console::error('[Error] Message: '.$response['data']['message']); } } finally { $register->get('pools')->reclaim(); @@ -492,7 +489,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $database = getConsoleDB(); if ($projectId !== 'console') { - $project = Authorization::skip(fn() => $database->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); $database = getProjectDB($project); } @@ -515,16 +512,16 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $message = json_decode($message, true); - if (is_null($message) || (!array_key_exists('type', $message) && !array_key_exists('data', $message))) { + if (is_null($message) || (! array_key_exists('type', $message) && ! array_key_exists('data', $message))) { throw new Exception('Message format is not valid.', 1003); } switch ($message['type']) { - /** + /** * This type is used to authenticate. */ case 'authentication': - if (!array_key_exists('session', $message['data'])) { + if (! array_key_exists('session', $message['data'])) { throw new Exception('Payload is not valid.', 1003); } @@ -537,7 +534,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re if ( empty($user->getId()) // Check a document has been found in the DB - || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) // Validate user has valid login token + || ! Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) // Validate user has valid login token ) { // cookie not valid throw new Exception('Session is not valid.', 1003); @@ -553,8 +550,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re 'data' => [ 'to' => 'authentication', 'success' => true, - 'user' => $user - ] + 'user' => $user, + ], ])); break; @@ -567,8 +564,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re 'type' => 'error', 'data' => [ 'code' => $th->getCode(), - 'message' => $th->getMessage() - ] + 'message' => $th->getMessage(), + ], ]; $server->send([$connection], json_encode($response)); @@ -587,7 +584,7 @@ $server->onClose(function (int $connection) use ($realtime, $stats) { } $realtime->unsubscribe($connection); - Console::info('Connection close: ' . $connection); + Console::info('Connection close: '.$connection); }); $server->start(); diff --git a/app/worker.php b/app/worker.php index ea086fa43d..bd7cf7970d 100644 --- a/app/worker.php +++ b/app/worker.php @@ -1,6 +1,6 @@ $register); +Server::setResource('register', fn () => $register); Server::setResource('dbForConsole', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); $database = $pools ->get('console') ->pop() - ->getResource() - ; + ->getResource(); $adapter = new Database($database, $cache); $adapter->setNamespace('console'); @@ -52,11 +51,11 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource() - ; + ->getResource(); $adapter = new Database($database, $cache); - $adapter->setNamespace('_' . $project->getInternalId()); + $adapter->setNamespace('_'.$project->getInternalId()); + return $adapter; }, ['cache', 'register', 'message', 'dbForConsole']); @@ -69,8 +68,7 @@ Server::setResource('cache', function (Registry $register) { $adapters[] = $pools ->get($value) ->pop() - ->getResource() - ; + ->getResource(); } return new Cache(new Sharding($adapters)); @@ -78,6 +76,7 @@ Server::setResource('cache', function (Registry $register) { Server::setResource('queueForFunctions', function (Registry $register) { $pools = $register->get('pools'); + return new Func( $pools ->get('queue') @@ -88,6 +87,7 @@ Server::setResource('queueForFunctions', function (Registry $register) { Server::setResource('queueForUsage', function (Registry $register) { $pools = $register->get('pools'); + return new Usage( $pools ->get('queue') @@ -96,7 +96,7 @@ Server::setResource('queueForUsage', function (Registry $register) { ); }, ['register']); -Server::setResource('log', fn() => new Log()); +Server::setResource('log', fn () => new Log()); Server::setResource('logger', function ($register) { return $register->get('logger'); @@ -137,12 +137,12 @@ $server } if ($logger && ($error->getCode() >= 500 || $error->getCode() === 0)) { - $log->setNamespace("appwrite-worker"); + $log->setNamespace('appwrite-worker'); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); - $log->setAction('appwrite-queue-' . App::getEnv('QUEUE')); + $log->setAction('appwrite-queue-'.App::getEnv('QUEUE')); $log->addTag('verboseType', get_class($error)); $log->addTag('code', $error->getCode()); $log->addExtra('file', $error->getFile()); @@ -155,11 +155,11 @@ $server $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('Usage stats log pushed with status code: ' . $responseCode); + Console::info('Usage stats log pushed with status code: '.$responseCode); } - Console::error('[Error] Type: ' . get_class($error)); - Console::error('[Error] Message: ' . $error->getMessage()); - Console::error('[Error] File: ' . $error->getFile()); - Console::error('[Error] Line: ' . $error->getLine()); + Console::error('[Error] Type: '.get_class($error)); + Console::error('[Error] Message: '.$error->getMessage()); + Console::error('[Error] File: '.$error->getFile()); + Console::error('[Error] Line: '.$error->getLine()); }); diff --git a/app/workers/audits.php b/app/workers/audits.php index 8369ec74ec..a304fd70bb 100644 --- a/app/workers/audits.php +++ b/app/workers/audits.php @@ -5,16 +5,16 @@ use Utopia\Audit\Audit; use Utopia\CLI\Console; use Utopia\Database\Document; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Audits V1 Worker'); -Console::success(APP_NAME . ' audits worker v1 has started'); +Console::success(APP_NAME.' audits worker v1 has started'); class AuditsV1 extends Worker { public function getName(): string { - return "audits"; + return 'audits'; } public function init(): void diff --git a/app/workers/builds.php b/app/workers/builds.php index 972eb5dd18..41c3cbdcc7 100644 --- a/app/workers/builds.php +++ b/app/workers/builds.php @@ -6,20 +6,20 @@ use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Resque\Worker; use Appwrite\Utopia\Response\Model\Deployment; use Executor\Executor; -use Utopia\Database\DateTime; use Utopia\App; use Utopia\CLI\Console; -use Utopia\Database\Helpers\ID; -use Utopia\DSN\DSN; -use Utopia\Database\Document; use Utopia\Config\Config; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Storage\Storage; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Builds V1 Worker'); -Console::success(APP_NAME . ' build worker v1 has started'); +Console::success(APP_NAME.' build worker v1 has started'); // TODO: Executor should return appropriate response codes. class BuildsV1 extends Worker @@ -28,7 +28,7 @@ class BuildsV1 extends Worker public function getName(): string { - return "builds"; + return 'builds'; } public function init(): void @@ -46,7 +46,7 @@ class BuildsV1 extends Worker switch ($type) { case BUILD_TYPE_DEPLOYMENT: case BUILD_TYPE_RETRY: - Console::info('Creating build for deployment: ' . $deployment->getId()); + Console::info('Creating build for deployment: '.$deployment->getId()); $this->buildDeployment($project, $resource, $deployment); break; @@ -81,7 +81,7 @@ class BuildsV1 extends Worker $key = $function->getAttribute('runtime'); $runtime = isset($runtimes[$key]) ? $runtimes[$key] : null; if (\is_null($runtime)) { - throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + throw new Exception('Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); } $connection = App::getEnv('_APP_CONNECTIONS_STORAGE', ''); /** @TODO : move this to the registry or someplace else */ @@ -90,7 +90,7 @@ class BuildsV1 extends Worker $dsn = new DSN($connection); $device = $dsn->getScheme(); } catch (\Exception $e) { - Console::error($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); + Console::error($e->getMessage().'Invalid DSN. Defaulting to Local device.'); } $buildId = $deployment->getAttribute('buildId', ''); @@ -111,7 +111,7 @@ class BuildsV1 extends Worker 'stdout' => '', 'stderr' => '', 'endTime' => null, - 'duration' => 0 + 'duration' => 0, ])); $deployment->setAttribute('buildId', $build->getId()); $deployment->setAttribute('buildInternalId', $build->getInternalId()); @@ -150,7 +150,7 @@ class BuildsV1 extends Worker /** Trigger Realtime */ $allEvents = Event::generateEvents('functions.[functionId].deployments.[deploymentId].update', [ 'functionId' => $function->getId(), - 'deploymentId' => $deployment->getId() + 'deploymentId' => $deployment->getId(), ]); $target = Realtime::fromPayload( // Pass first, most verbose event pattern @@ -171,6 +171,7 @@ class BuildsV1 extends Worker $vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) { $carry[$var->getAttribute('key')] = $var->getAttribute('value'); + return $carry; }, []); @@ -183,12 +184,12 @@ class BuildsV1 extends Worker remove: true, entrypoint: $deployment->getAttribute('entrypoint'), workdir: '/usr/code', - destination: APP_STORAGE_BUILDS . "/app-{$project->getId()}", + destination: APP_STORAGE_BUILDS."/app-{$project->getId()}", variables: $vars, commands: [ 'sh', '-c', 'tar -zxf /tmp/code.tar.gz -C /usr/code && \ - cd /usr/local/src/ && ./build.sh' + cd /usr/local/src/ && ./build.sh', ] ); @@ -222,8 +223,7 @@ class BuildsV1 extends Worker $schedule ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - + ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); } catch (\Throwable $th) { @@ -261,12 +261,11 @@ class BuildsV1 extends Worker ->setProject($project) ->addMetric(METRIC_BUILDS, 1) // per project ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) - ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(METRIC_BUILDS_COMPUTE, (int) $build->getAttribute('duration', 0) * 1000) ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) - ->trigger() - ; + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int) $build->getAttribute('duration', 0) * 1000) + ->trigger(); } public function shutdown(): void diff --git a/app/workers/certificates.php b/app/workers/certificates.php index 824a296b75..fc72f6d4e6 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -7,17 +7,17 @@ use Appwrite\Template\Template; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Domains\Domain; use Utopia\Locale\Locale; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Certificates V1 Worker'); -Console::success(APP_NAME . ' certificates worker v1 has started'); +Console::success(APP_NAME.' certificates worker v1 has started'); class CertificatesV1 extends Worker { @@ -30,7 +30,7 @@ class CertificatesV1 extends Worker public function getName(): string { - return "certificates"; + return 'certificates'; } public function init(): void @@ -68,7 +68,6 @@ class CertificatesV1 extends Worker * * Note: Renewals are checked and scheduled from maintenence worker */ - $this->dbForConsole = $this->getConsoleDB(); $skipCheck = $this->args['skipRenewCheck'] ?? false; // If true, we won't double-check expiry from cert file @@ -79,7 +78,7 @@ class CertificatesV1 extends Worker $certificate = $this->dbForConsole->findOne('certificates', [Query::equal('domain', [$domain->get()])]); // If we don't have certificate for domain yet, let's create new document. At the end we save it - if (!$certificate) { + if (! $certificate) { $certificate = new Document(); $certificate->setAttribute('domain', $domain->get()); } @@ -92,14 +91,14 @@ class CertificatesV1 extends Worker } // Validate domain and DNS records. Skip if job is forced - if (!$skipCheck) { + if (! $skipCheck) { $mainDomain = $this->getMainDomain(); - $isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain; + $isMainDomain = ! isset($mainDomain) || $domain->get() === $mainDomain; $this->validateDomain($domain, $isMainDomain); } // If certificate exists already, double-check expiry date. Skip if job is forced - if (!$skipCheck && !$this->isRenewRequired($domain->get())) { + if (! $skipCheck && ! $this->isRenewRequired($domain->get())) { throw new Exception('Renew isn\'t required.'); } @@ -152,16 +151,15 @@ class CertificatesV1 extends Worker /** * Save certificate data into database. * - * @param string $domain Domain name that certificate is for - * @param Document $certificate Certificate document that we need to save - * + * @param string $domain Domain name that certificate is for + * @param Document $certificate Certificate document that we need to save * @return void */ private function saveCertificateDocument(string $domain, Document $certificate): void { // Check if update or insert required $certificateDocument = $this->dbForConsole->findOne('certificates', [Query::equal('domain', [$domain])]); - if (!empty($certificateDocument) && !$certificateDocument->isEmpty()) { + if (! empty($certificateDocument) && ! $certificateDocument->isEmpty()) { // Merge new data with current data $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); @@ -182,7 +180,7 @@ class CertificatesV1 extends Worker private function getMainDomain(): ?string { $envDomain = App::getEnv('_APP_DOMAIN', ''); - if (!empty($envDomain) && $envDomain !== 'localhost') { + if (! empty($envDomain) && $envDomain !== 'localhost') { return $envDomain; } else { $domainDocument = $this->dbForConsole->findOne('domains', [Query::orderAsc('_id')]); @@ -199,9 +197,8 @@ class CertificatesV1 extends Worker * - Domain needs to be public and valid (prevents NFT domains that are not supported by Let's Encrypt) * - Domain must have proper DNS record * - * @param Domain $domain Domain which we validate - * @param bool $isMainDomain In case of master domain, we look for different DNS configurations - * + * @param Domain $domain Domain which we validate + * @param bool $isMainDomain In case of master domain, we look for different DNS configurations * @return void */ private function validateDomain(Domain $domain, bool $isMainDomain): void @@ -210,23 +207,23 @@ class CertificatesV1 extends Worker throw new Exception('Missing certificate domain.'); } - if (!$domain->isKnown() || $domain->isTest()) { + if (! $domain->isKnown() || $domain->isTest()) { throw new Exception('Unknown public suffix for domain.'); } - if (!$isMainDomain) { + if (! $isMainDomain) { // TODO: Would be awesome to also support A/AAAA records here. Maybe dry run? // Validate if domain target is properly configured $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - if (!$target->isKnown() || $target->isTest()) { - throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.'); + if (! $target->isKnown() || $target->isTest()) { + throw new Exception('Unreachable CNAME target ('.$target->get().'), please use a domain with a public suffix.'); } // Verify domain with DNS records $validator = new CNAME($target->get()); - if (!$validator->isValid($domain->get())) { + if (! $validator->isValid($domain->get())) { throw new Exception('Failed to verify domain DNS records.'); } } else { @@ -238,13 +235,12 @@ class CertificatesV1 extends Worker /** * Reads expiry date of certificate from file and decides if renewal is required or not. * - * @param string $domain Domain for which we check certificate file - * + * @param string $domain Domain for which we check certificate file * @return bool True, if certificate needs to be renewed */ private function isRenewRequired(string $domain): bool { - $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; + $certPath = APP_STORAGE_CERTIFICATES.'/'.$domain.'/cert.pem'; if (\file_exists($certPath)) { $validTo = null; @@ -268,9 +264,8 @@ class CertificatesV1 extends Worker /** * LetsEncrypt communication to issue certificate (using certbot CLI) * - * @param string $folder Folder into which certificates should be generated - * @param string $domain Domain to generate certificate for - * + * @param string $folder Folder into which certificates should be generated + * @param string $domain Domain to generate certificate for * @return array Named array with keys 'stdout' and 'stderr', both string */ private function issueCertificate(string $folder, string $domain, string $email): array @@ -280,83 +275,82 @@ class CertificatesV1 extends Worker $staging = (App::isProduction()) ? '' : ' --dry-run'; $exit = Console::execute("certbot certonly --webroot --noninteractive --agree-tos{$staging}" - . " --email " . $email - . " --cert-name " . $folder - . " -w " . APP_STORAGE_CERTIFICATES - . " -d {$domain}", '', $stdout, $stderr); + .' --email '.$email + .' --cert-name '.$folder + .' -w '.APP_STORAGE_CERTIFICATES + ." -d {$domain}", '', $stdout, $stderr); // Unexpected error, usually 5XX, API limits, ... if ($exit !== 0) { - throw new Exception('Failed to issue a certificate with message: ' . $stderr); + throw new Exception('Failed to issue a certificate with message: '.$stderr); } return [ 'stdout' => $stdout, - 'stderr' => $stderr + 'stderr' => $stderr, ]; } /** * Read new renew date from certificate file generated by Let's Encrypt * - * @param string $domain Domain which certificate was generated for - * + * @param string $domain Domain which certificate was generated for * @return string */ private function getRenewDate(string $domain): string { - $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; + $certPath = APP_STORAGE_CERTIFICATES.'/'.$domain.'/cert.pem'; $certData = openssl_x509_parse(file_get_contents($certPath)); $validTo = $certData['validTo_time_t'] ?? null; $dt = (new \DateTime())->setTimestamp($validTo); + return DateTime::addSeconds($dt, -60 * 60 * 24 * 30); // -30 days } /** * Method to take files from Let's Encrypt, and put it into Traefik. * - * @param string $domain Domain which certificate was generated for - * @param string $folder Folder in which certificates were generated - * @param array $letsEncryptData Let's Encrypt logs to use for additional info when throwing error - * + * @param string $domain Domain which certificate was generated for + * @param string $folder Folder in which certificates were generated + * @param array $letsEncryptData Let's Encrypt logs to use for additional info when throwing error * @return void */ private function applyCertificateFiles(string $folder, string $domain, array $letsEncryptData): void { // Prepare folder in storage for domain - $path = APP_STORAGE_CERTIFICATES . '/' . $domain; - if (!\is_readable($path)) { - if (!\mkdir($path, 0755, true)) { + $path = APP_STORAGE_CERTIFICATES.'/'.$domain; + if (! \is_readable($path)) { + if (! \mkdir($path, 0755, true)) { throw new Exception('Failed to create path for certificate.'); } } // Move generated files - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) { - throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); + if (! @\rename('/etc/letsencrypt/live/'.$folder.'/cert.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/cert.pem')) { + throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); } - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) { - throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); + if (! @\rename('/etc/letsencrypt/live/'.$folder.'/chain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/chain.pem')) { + throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); } - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/fullchain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/fullchain.pem')) { - throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); + if (! @\rename('/etc/letsencrypt/live/'.$folder.'/fullchain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/fullchain.pem')) { + throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); } - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/privkey.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/privkey.pem')) { - throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); + if (! @\rename('/etc/letsencrypt/live/'.$folder.'/privkey.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/privkey.pem')) { + throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); } $config = \implode(PHP_EOL, [ - "tls:", - " certificates:", + 'tls:', + ' certificates:', " - certFile: /storage/certificates/{$domain}/fullchain.pem", - " keyFile: /storage/certificates/{$domain}/privkey.pem" + " keyFile: /storage/certificates/{$domain}/privkey.pem", ]); // Save configuration into Traefik using our new cert files - if (!\file_put_contents(APP_STORAGE_CONFIG . '/' . $domain . '.yml', $config)) { + if (! \file_put_contents(APP_STORAGE_CONFIG.'/'.$domain.'.yml', $config)) { throw new Exception('Failed to save Traefik configuration.'); } } @@ -364,39 +358,38 @@ class CertificatesV1 extends Worker /** * Method to make sure information about error is delivered to admnistrator. * - * @param string $domain Domain that caused the error - * @param string $errorMessage Verbose error message - * @param int $attempt How many times it failed already - * + * @param string $domain Domain that caused the error + * @param string $errorMessage Verbose error message + * @param int $attempt How many times it failed already * @return void */ private function notifyError(string $domain, string $errorMessage, int $attempt): void { // Log error into console - Console::warning('Cannot renew domain (' . $domain . ') on attempt no. ' . $attempt . ' certificate: ' . $errorMessage); + Console::warning('Cannot renew domain ('.$domain.') on attempt no. '.$attempt.' certificate: '.$errorMessage); // Send mail to administratore mail $locale = new Locale(App::getEnv('_APP_LOCALE', 'en')); - if (!$locale->getText('emails.sender') || !$locale->getText("emails.certificate.hello") || !$locale->getText("emails.certificate.subject") || !$locale->getText("emails.certificate.body") || !$locale->getText("emails.certificate.footer") || !$locale->getText("emails.certificate.thanks") || !$locale->getText("emails.certificate.signature")) { + if (! $locale->getText('emails.sender') || ! $locale->getText('emails.certificate.hello') || ! $locale->getText('emails.certificate.subject') || ! $locale->getText('emails.certificate.body') || ! $locale->getText('emails.certificate.footer') || ! $locale->getText('emails.certificate.thanks') || ! $locale->getText('emails.certificate.signature')) { $locale->setDefault('en'); } - $body = Template::fromFile(__DIR__ . '/../config/locale/templates/email-base.tpl'); + $body = Template::fromFile(__DIR__.'/../config/locale/templates/email-base.tpl'); - $subject = \sprintf($locale->getText("emails.certificate.subject"), $domain); - $body->setParam('{{domain}}', $domain); - $body->setParam('{{error}}', $errorMessage); - $body->setParam('{{attempt}}', $attempt); + $subject = \sprintf($locale->getText('emails.certificate.subject'), $domain); + $body->setParam('{{domain}}', $domain); + $body->setParam('{{error}}', $errorMessage); + $body->setParam('{{attempt}}', $attempt); $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText("emails.certificate.hello")) - ->setParam('{{body}}', $locale->getText("emails.certificate.body")) - ->setParam('{{redirect}}', 'https://' . $domain) - ->setParam('{{footer}}', $locale->getText("emails.certificate.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.certificate.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.certificate.signature")) + ->setParam('{{hello}}', $locale->getText('emails.certificate.hello')) + ->setParam('{{body}}', $locale->getText('emails.certificate.body')) + ->setParam('{{redirect}}', 'https://'.$domain) + ->setParam('{{footer}}', $locale->getText('emails.certificate.footer')) + ->setParam('{{thanks}}', $locale->getText('emails.certificate.thanks')) + ->setParam('{{signature}}', $locale->getText('emails.certificate.signature')) ->setParam('{{project}}', 'Console') ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -418,9 +411,8 @@ class CertificatesV1 extends Worker * - when renew creates new document? It might? * - overall makes it more reliable * - * @param string $certificateId ID of a new or updated certificate document - * @param string $domain Domain that is affected by new certificate - * + * @param string $certificateId ID of a new or updated certificate document + * @param string $domain Domain that is affected by new certificate * @return void */ private function updateDomainDocuments(string $certificateId, string $domain): void diff --git a/app/workers/databases.php b/app/workers/databases.php index 764f668f33..6490c7a8d9 100644 --- a/app/workers/databases.php +++ b/app/workers/databases.php @@ -9,10 +9,10 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Database V1 Worker'); -Console::success(APP_NAME . ' database worker v1 has started' . "\n"); +Console::success(APP_NAME.' database worker v1 has started'."\n"); class DatabaseV1 extends Worker { @@ -51,7 +51,7 @@ class DatabaseV1 extends Worker break; default: - Console::error('No database operation for type: ' . $type); + Console::error('No database operation for type: '.$type); break; } } @@ -61,10 +61,10 @@ class DatabaseV1 extends Worker } /** - * @param Document $database - * @param Document $collection - * @param Document $attribute - * @param Document $project + * @param Document $database + * @param Document $collection + * @param Document $attribute + * @param Document $project */ protected function createAttribute(Document $database, Document $collection, Document $attribute, Document $project): void { @@ -75,7 +75,7 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].update', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'attributeId' => $attribute->getId() + 'attributeId' => $attribute->getId(), ]); /** * Fetch attribute from the database, since with Resque float values are loosing informations. @@ -99,15 +99,15 @@ class DatabaseV1 extends Worker try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_'.$database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } if ( - !$dbForProject->createRelationship( - collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + ! $dbForProject->createRelationship( + collection: 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), + relatedCollection: 'database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -119,12 +119,12 @@ class DatabaseV1 extends Worker } if ($options['twoWay']) { - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$options['twoWayKey']); $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); } break; default: - if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if (! $dbForProject->createAttribute('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } } @@ -170,23 +170,24 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId() + 'collectionId' => $collection->getId(), ] ); } if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $relatedCollection->getId()); } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collectionId); } /** - * @param Document $database - * @param Document $collection - * @param Document $attribute - * @param Document $project + * @param Document $database + * @param Document $collection + * @param Document $attribute + * @param Document $project + * * @throws Throwable */ protected function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project): void @@ -198,7 +199,7 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'attributeId' => $attribute->getId() + 'attributeId' => $attribute->getId(), ]); $collectionId = $collection->getId(); $key = $attribute->getAttribute('key', ''); @@ -219,25 +220,25 @@ class DatabaseV1 extends Worker if ($status !== 'failed') { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_'.$database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$options['twoWayKey']); } - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if (! $dbForProject->deleteRelationship('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key)) { $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + } elseif (! $dbForProject->deleteAttribute('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete Attribute'); } } $dbForProject->deleteDocument('attributes', $attribute->getId()); - if (!$relatedAttribute->isEmpty()) { + if (! $relatedAttribute->isEmpty()) { $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } } catch (\Exception $e) { @@ -245,7 +246,7 @@ class DatabaseV1 extends Worker if ($e instanceof DatabaseException) { $attribute->setAttribute('error', $e->getMessage()); - if (!$relatedAttribute->isEmpty()) { + if (! $relatedAttribute->isEmpty()) { $relatedAttribute->setAttribute('error', $e->getMessage()); } } @@ -254,7 +255,7 @@ class DatabaseV1 extends Worker $attribute->getId(), $attribute->setAttribute('status', 'stuck') ); - if (!$relatedAttribute->isEmpty()) { + if (! $relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), @@ -278,7 +279,7 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId() + 'collectionId' => $collection->getId(), ] ); } @@ -334,20 +335,21 @@ class DatabaseV1 extends Worker } } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId()); - if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + if (! $relatedCollection->isEmpty() && ! $relatedAttribute->isEmpty()) { + $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId()); } } /** - * @param Document $database - * @param Document $collection - * @param Document $index - * @param Document $project + * @param Document $database + * @param Document $collection + * @param Document $index + * @param Document $project + * * @throws \Exception */ protected function createIndex(Document $database, Document $collection, Document $index, Document $project): void @@ -359,7 +361,7 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].update', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'indexId' => $index->getId() + 'indexId' => $index->getId(), ]); $collectionId = $collection->getId(); $key = $index->getAttribute('key', ''); @@ -370,7 +372,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (! $dbForProject->createIndex('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -402,19 +404,19 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId() + 'collectionId' => $collection->getId(), ] ); } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collectionId); } /** - * @param Document $database - * @param Document $collection - * @param Document $index - * @param Document $project + * @param Document $database + * @param Document $collection + * @param Document $index + * @param Document $project */ protected function deleteIndex(Document $database, Document $collection, Document $index, Document $project): void { @@ -425,14 +427,14 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].delete', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'indexId' => $index->getId() + 'indexId' => $index->getId(), ]); $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); $project = $dbForConsole->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if ($status !== 'failed' && ! $dbForProject->deleteIndex('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -464,11 +466,11 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId() + 'collectionId' => $collection->getId(), ] ); } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collection->getId()); } } diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 7f426bf4f4..7d276f22cf 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -1,29 +1,29 @@ deleteCollection($document, $project); break; } - Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); + Console::error('No lazy delete operation available for document of type: '.$document->getCollection()); break; } break; @@ -82,14 +82,14 @@ class DeletesV1 extends Worker case DELETE_TYPE_AUDIT: $datetime = $this->args['datetime'] ?? null; - if (!empty($datetime)) { + if (! empty($datetime)) { $this->deleteAuditLogs($datetime); } $document = new Document($this->args['document'] ?? []); - if (!$document->isEmpty()) { - $this->deleteAuditLogsByResource('document/' . $document->getId(), $project); + if (! $document->isEmpty()) { + $this->deleteAuditLogsByResource('document/'.$document->getId(), $project); } break; @@ -125,7 +125,7 @@ class DeletesV1 extends Worker $this->deleteSchedules($this->args['datetime']); break; default: - Console::error('No delete operation for type: ' . $type); + Console::error('No delete operation for type: '.$type); break; } } @@ -153,7 +153,8 @@ class DeletesV1 extends Worker if ($project->isEmpty()) { $this->getConsoleDB()->deleteDocument('schedules', $document->getId()); - Console::success('Deleted schedule for deleted project ' . $document->getAttribute('projectId')); + Console::success('Deleted schedule for deleted project '.$document->getAttribute('projectId')); + return; } @@ -161,15 +162,16 @@ class DeletesV1 extends Worker if ($function->isEmpty()) { $this->getConsoleDB()->deleteDocument('schedules', $document->getId()); - Console::success('Deleted schedule for function ' . $document->getAttribute('resourceId')); + Console::success('Deleted schedule for function '.$document->getAttribute('resourceId')); } } ); } /** - * @param Document $project - * @param string $resource + * @param Document $project + * @param string $resource + * * @throws Exception */ protected function deleteCacheByResource(Document $project, string $resource): void @@ -180,19 +182,19 @@ class DeletesV1 extends Worker if ($document) { $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) + new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId) ); $this->deleteById( $document, $dbForProject, function ($document) use ($cache, $projectId) { - $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); + $path = APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId.DIRECTORY_SEPARATOR.$document->getId(); if ($cache->purge($document->getId())) { - Console::success('Deleting cache file: ' . $path); + Console::success('Deleting cache file: '.$path); } else { - Console::error('Failed to delete cache file: ' . $path); + Console::error('Failed to delete cache file: '.$path); } } ); @@ -200,7 +202,8 @@ class DeletesV1 extends Worker } /** - * @param string $datetime + * @param string $datetime + * * @throws Exception */ protected function deleteCacheByDate(string $datetime): void @@ -209,7 +212,7 @@ class DeletesV1 extends Worker $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) + new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId) ); $query = [ @@ -221,22 +224,21 @@ class DeletesV1 extends Worker $query, $dbForProject, function (Document $document) use ($cache, $projectId) { - $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); + $path = APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId.DIRECTORY_SEPARATOR.$document->getId(); if ($cache->purge($document->getId())) { - Console::success('Deleting cache file: ' . $path); + Console::success('Deleting cache file: '.$path); } else { - Console::error('Failed to delete cache file: ' . $path); + Console::error('Failed to delete cache file: '.$path); } } ); }); } - /** - * @param Document $document database document - * @param Document $project + * @param Document $document database document + * @param Document $project */ protected function deleteDatabase(Document $document, Document $project): void { @@ -245,18 +247,18 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); - $this->deleteByGroup('database_' . $document->getInternalId(), [], $dbForProject, function ($document) use ($project) { + $this->deleteByGroup('database_'.$document->getInternalId(), [], $dbForProject, function ($document) use ($project) { $this->deleteCollection($document, $project); }); - $dbForProject->deleteCollection('database_' . $document->getInternalId()); + $dbForProject->deleteCollection('database_'.$document->getInternalId()); - $this->deleteAuditLogsByResource('database/' . $databaseId, $project); + $this->deleteAuditLogsByResource('database/'.$databaseId, $project); } /** - * @param Document $document teams document - * @param Document $project + * @param Document $document teams document + * @param Document $project */ protected function deleteCollection(Document $document, Document $project): void { @@ -273,32 +275,33 @@ class DeletesV1 extends Worker ); foreach ($relationships as $relationship) { - if (!$relationship['twoWay']) { + if (! $relationship['twoWay']) { continue; } - $relatedCollection = $dbForProject->getDocument('database_' . $databaseInternalId, $relationship['relatedCollection']); - $dbForProject->deleteDocument('attributes', $databaseInternalId . '_' . $relatedCollection->getInternalId() . '_' . $relationship['twoWayKey']); - $dbForProject->deleteCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId()); + $relatedCollection = $dbForProject->getDocument('database_'.$databaseInternalId, $relationship['relatedCollection']); + $dbForProject->deleteDocument('attributes', $databaseInternalId.'_'.$relatedCollection->getInternalId().'_'.$relationship['twoWayKey']); + $dbForProject->deleteCachedDocument('database_'.$databaseInternalId, $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_'.$databaseInternalId.'_collection_'.$relatedCollection->getInternalId()); } - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); + $dbForProject->deleteCollection('database_'.$databaseInternalId.'_collection_'.$document->getInternalId()); $this->deleteByGroup('attributes', [ Query::equal('databaseInternalId', [$databaseInternalId]), - Query::equal('collectionInternalId', [$collectionInternalId]) + Query::equal('collectionInternalId', [$collectionInternalId]), ], $dbForProject); $this->deleteByGroup('indexes', [ Query::equal('databaseInternalId', [$databaseInternalId]), - Query::equal('collectionInternalId', [$collectionInternalId]) + Query::equal('collectionInternalId', [$collectionInternalId]), ], $dbForProject); - $this->deleteAuditLogsByResource('database/' . $databaseId . '/collection/' . $collectionId, $project); + $this->deleteAuditLogsByResource('database/'.$databaseId.'/collection/'.$collectionId, $project); } /** - * @param string $hourlyUsageRetentionDatetime + * @param string $hourlyUsageRetentionDatetime + * * @throws Exception */ protected function deleteUsageStats(string $hourlyUsageRetentionDatetime) @@ -314,8 +317,8 @@ class DeletesV1 extends Worker } /** - * @param Document $document teams document - * @param Document $project + * @param Document $document teams document + * @param Document $project */ protected function deleteMemberships(Document $document, Document $project): void { @@ -326,7 +329,7 @@ class DeletesV1 extends Worker $this->deleteByGroup( 'memberships', [ - Query::equal('teamInternalId', [$teamInternalId]) + Query::equal('teamInternalId', [$teamInternalId]), ], $dbForProject, function (Document $membership) use ($dbForProject) { @@ -337,8 +340,9 @@ class DeletesV1 extends Worker } /** - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return void + * * @throws \Exception */ protected function deleteProjectsByTeam(Document $document): void @@ -346,7 +350,7 @@ class DeletesV1 extends Worker $dbForConsole = $this->getConsoleDB(); $projects = $dbForConsole->find('projects', [ - Query::equal('teamInternalId', [$document->getInternalId()]) + Query::equal('teamInternalId', [$document->getInternalId()]), ]); foreach ($projects as $project) { @@ -356,7 +360,8 @@ class DeletesV1 extends Worker } /** - * @param Document $document project document + * @param Document $document project document + * * @throws Exception */ protected function deleteProject(Document $document): void @@ -368,7 +373,7 @@ class DeletesV1 extends Worker $dbForConsole = $this->getConsoleDB(); $domains = $dbForConsole->find('domains', [ - Query::equal('projectInternalId', [$projectInternalId]) + Query::equal('projectInternalId', [$projectInternalId]), ]); foreach ($domains as $domain) { @@ -392,22 +397,22 @@ class DeletesV1 extends Worker // Delete Platforms $this->deleteByGroup('platforms', [ - Query::equal('projectInternalId', [$projectInternalId]) + Query::equal('projectInternalId', [$projectInternalId]), ], $dbForConsole); // Delete Domains $this->deleteByGroup('domains', [ - Query::equal('projectInternalId', [$projectInternalId]) + Query::equal('projectInternalId', [$projectInternalId]), ], $dbForConsole); // Delete Keys $this->deleteByGroup('keys', [ - Query::equal('projectInternalId', [$projectInternalId]) + Query::equal('projectInternalId', [$projectInternalId]), ], $dbForConsole); // Delete Webhooks $this->deleteByGroup('webhooks', [ - Query::equal('projectInternalId', [$projectInternalId]) + Query::equal('projectInternalId', [$projectInternalId]), ], $dbForConsole); // Delete metadata tables @@ -431,8 +436,8 @@ class DeletesV1 extends Worker } /** - * @param Document $document user document - * @param Document $project + * @param Document $document user document + * @param Document $project */ protected function deleteUser(Document $document, Document $project): void { @@ -443,19 +448,19 @@ class DeletesV1 extends Worker // Delete all sessions of this user from the sessions table and update the sessions field of the user record $this->deleteByGroup('sessions', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), ], $dbForProject); $dbForProject->deleteCachedDocument('users', $userId); // Delete Memberships and decrement team membership counts $this->deleteByGroup('memberships', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), ], $dbForProject, function (Document $document) use ($dbForProject) { if ($document->getAttribute('confirm')) { // Count only confirmed members $teamId = $document->getAttribute('teamId'); $team = $dbForProject->getDocument('teams', $teamId); - if (!$team->isEmpty()) { + if (! $team->isEmpty()) { $team = $dbForProject->updateDocument( 'teams', $teamId, @@ -468,17 +473,18 @@ class DeletesV1 extends Worker // Delete tokens $this->deleteByGroup('tokens', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), ], $dbForProject); // Delete identities $this->deleteByGroup('identities', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), ], $dbForProject); } /** - * @param string $datetime + * @param string $datetime + * * @throws Exception */ protected function deleteExecutionLogs(string $datetime): void @@ -487,7 +493,7 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); // Delete Executions $this->deleteByGroup('executions', [ - Query::lessThan('$createdAt', $datetime) + Query::lessThan('$createdAt', $datetime), ], $dbForProject); }); } @@ -505,13 +511,14 @@ class DeletesV1 extends Worker // Delete Sessions $this->deleteByGroup('sessions', [ - Query::lessThan('$createdAt', $expired) + Query::lessThan('$createdAt', $expired), ], $dbForProject); }); } /** - * @param string $datetime + * @param string $datetime + * * @throws Exception */ protected function deleteRealtimeUsage(string $datetime): void @@ -520,13 +527,14 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); // Delete Dead Realtime Logs $this->deleteByGroup('realtime', [ - Query::lessThan('timestamp', $datetime) + Query::lessThan('timestamp', $datetime), ], $dbForProject); }); } /** - * @param string $datetime + * @param string $datetime + * * @throws Exception */ protected function deleteAbuseLogs(string $datetime): void @@ -538,17 +546,18 @@ class DeletesV1 extends Worker $this->deleteForProjectIds(function (Document $project) use ($datetime) { $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); - $timeLimit = new TimeLimit("", 0, 1, $dbForProject); + $timeLimit = new TimeLimit('', 0, 1, $dbForProject); $abuse = new Abuse($timeLimit); $status = $abuse->cleanup($datetime); - if (!$status) { - throw new Exception('Failed to delete Abuse logs for project ' . $projectId); + if (! $status) { + throw new Exception('Failed to delete Abuse logs for project '.$projectId); } }); } /** - * @param string $datetime + * @param string $datetime + * * @throws Exception */ protected function deleteAuditLogs(string $datetime): void @@ -562,28 +571,28 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); $audit = new Audit($dbForProject); $status = $audit->cleanup($datetime); - if (!$status) { - throw new Exception('Failed to delete Audit logs for project' . $projectId); + if (! $status) { + throw new Exception('Failed to delete Audit logs for project'.$projectId); } }); } /** - * @param string $resource - * @param Document $project + * @param string $resource + * @param Document $project */ protected function deleteAuditLogsByResource(string $resource, Document $project): void { $dbForProject = $this->getProjectDB($project); $this->deleteByGroup(Audit::COLLECTION, [ - Query::equal('resource', [$resource]) + Query::equal('resource', [$resource]), ], $dbForProject); } /** - * @param Document $document function document - * @param Document $project + * @param Document $document function document + * @param Document $project */ protected function deleteFunction(Document $document, Document $project): void { @@ -595,41 +604,41 @@ class DeletesV1 extends Worker /** * Delete Variables */ - Console::info("Deleting variables for function " . $functionId); + Console::info('Deleting variables for function '.$functionId); $this->deleteByGroup('variables', [ - Query::equal('functionInternalId', [$functionInternalId]) + Query::equal('functionInternalId', [$functionInternalId]), ], $dbForProject); /** * Delete Deployments */ - Console::info("Deleting deployments for function " . $functionId); + Console::info('Deleting deployments for function '.$functionId); $storageFunctions = $this->getFunctionsDevice($projectId); $deploymentIds = []; $this->deleteByGroup('deployments', [ - Query::equal('resourceId', [$functionId]) + Query::equal('resourceId', [$functionId]), ], $dbForProject, function (Document $document) use ($storageFunctions, &$deploymentIds) { $deploymentIds[] = $document->getId(); if ($storageFunctions->delete($document->getAttribute('path', ''), true)) { - Console::success('Deleted deployment files: ' . $document->getAttribute('path', '')); + Console::success('Deleted deployment files: '.$document->getAttribute('path', '')); } else { - Console::error('Failed to delete deployment files: ' . $document->getAttribute('path', '')); + Console::error('Failed to delete deployment files: '.$document->getAttribute('path', '')); } }); /** * Delete builds */ - Console::info("Deleting builds for function " . $functionId); + Console::info('Deleting builds for function '.$functionId); $storageBuilds = $this->getBuildsDevice($projectId); foreach ($deploymentIds as $deploymentId) { $this->deleteByGroup('builds', [ - Query::equal('deploymentId', [$deploymentId]) - ], $dbForProject, function (Document $document) use ($storageBuilds, $deploymentId) { + Query::equal('deploymentId', [$deploymentId]), + ], $dbForProject, function (Document $document) use ($storageBuilds) { if ($storageBuilds->delete($document->getAttribute('outputPath', ''), true)) { - Console::success('Deleted build files: ' . $document->getAttribute('outputPath', '')); + Console::success('Deleted build files: '.$document->getAttribute('outputPath', '')); } else { - Console::error('Failed to delete build files: ' . $document->getAttribute('outputPath', '')); + Console::error('Failed to delete build files: '.$document->getAttribute('outputPath', '')); } }); } @@ -637,17 +646,17 @@ class DeletesV1 extends Worker /** * Delete Executions */ - Console::info("Deleting executions for function " . $functionId); + Console::info('Deleting executions for function '.$functionId); $this->deleteByGroup('executions', [ - Query::equal('functionId', [$functionId]) + Query::equal('functionId', [$functionId]), ], $dbForProject); // TODO: Request executor to delete runtime } /** - * @param Document $document deployment document - * @param Document $project + * @param Document $document deployment document + * @param Document $project */ protected function deleteDeployment(Document $document, Document $project): void { @@ -659,45 +668,44 @@ class DeletesV1 extends Worker /** * Delete deployment files */ - Console::info("Deleting deployment files for deployment " . $deploymentId); + Console::info('Deleting deployment files for deployment '.$deploymentId); $storageFunctions = $this->getFunctionsDevice($projectId); if ($storageFunctions->delete($document->getAttribute('path', ''), true)) { - Console::success('Deleted deployment files: ' . $document->getAttribute('path', '')); + Console::success('Deleted deployment files: '.$document->getAttribute('path', '')); } else { - Console::error('Failed to delete deployment files: ' . $document->getAttribute('path', '')); + Console::error('Failed to delete deployment files: '.$document->getAttribute('path', '')); } /** * Delete builds */ - Console::info("Deleting builds for deployment " . $deploymentId); + Console::info('Deleting builds for deployment '.$deploymentId); $storageBuilds = $this->getBuildsDevice($projectId); $this->deleteByGroup('builds', [ - Query::equal('deploymentId', [$deploymentId]) + Query::equal('deploymentId', [$deploymentId]), ], $dbForProject, function (Document $document) use ($storageBuilds) { if ($storageBuilds->delete($document->getAttribute('outputPath', ''), true)) { - Console::success('Deleted build files: ' . $document->getAttribute('outputPath', '')); + Console::success('Deleted build files: '.$document->getAttribute('outputPath', '')); } else { - Console::error('Failed to delete build files: ' . $document->getAttribute('outputPath', '')); + Console::error('Failed to delete build files: '.$document->getAttribute('outputPath', '')); } }); // TODO: Request executor to delete runtime } - /** - * @param Document $document to be deleted - * @param Database $database to delete it from - * @param callable|null $callback to perform after document is deleted - * + * @param Document $document to be deleted + * @param Database $database to delete it from + * @param callable|null $callback to perform after document is deleted * @return bool + * * @throws \Utopia\Database\Exception\Authorization */ protected function deleteById(Document $document, Database $database, callable $callback = null): bool { if ($database->deleteDocument($document->getCollection(), $document->getId())) { - Console::success('Deleted document "' . $document->getId() . '" successfully'); + Console::success('Deleted document "'.$document->getId().'" successfully'); if (is_callable($callback)) { $callback($document); @@ -705,13 +713,15 @@ class DeletesV1 extends Worker return true; } else { - Console::error('Failed to delete document: ' . $document->getId()); + Console::error('Failed to delete document: '.$document->getId()); + return false; } } /** - * @param callable $callback + * @param callable $callback + * * @throws Exception */ protected function deleteForProjectIds(callable $callback): void @@ -733,7 +743,7 @@ class DeletesV1 extends Worker /** @var string[] $projectIds */ $sum = count($projects); - Console::info('Executing delete function for chunk #' . $chunk . '. Found ' . $sum . ' projects'); + Console::info('Executing delete function for chunk #'.$chunk.'. Found '.$sum.' projects'); foreach ($projects as $project) { $callback($project); $count++; @@ -741,14 +751,15 @@ class DeletesV1 extends Worker } $executionEnd = \microtime(true); - Console::info("Found {$count} projects " . ($executionEnd - $executionStart) . " seconds"); + Console::info("Found {$count} projects ".($executionEnd - $executionStart).' seconds'); } /** - * @param string $collection collectionID - * @param array $queries - * @param Database $database - * @param callable|null $callback + * @param string $collection collectionID + * @param array $queries + * @param Database $database + * @param callable|null $callback + * * @throws Exception */ protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void @@ -769,7 +780,7 @@ class DeletesV1 extends Worker $sum = count($results); - Console::info('Deleting chunk #' . $chunk . '. Found ' . $sum . ' documents in collection ' . $database->getNamespace() . '_' . $collection); + Console::info('Deleting chunk #'.$chunk.'. Found '.$sum.' documents in collection '.$database->getNamespace().'_'.$collection); foreach ($results as $document) { $this->deleteById($document, $database, $callback); @@ -782,14 +793,14 @@ class DeletesV1 extends Worker $executionEnd = \microtime(true); - Console::info("Deleted {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); + Console::info("Deleted {$count} document by group in ".($executionEnd - $executionStart).' seconds'); } /** - * @param string $collection collectionID - * @param Query[] $queries - * @param Database $database - * @param callable $callback + * @param string $collection collectionID + * @param Query[] $queries + * @param Database $database + * @param callable $callback */ protected function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void { @@ -829,11 +840,12 @@ class DeletesV1 extends Worker $executionEnd = \microtime(true); - Console::info("Listed {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); + Console::info("Listed {$count} document by group in ".($executionEnd - $executionStart).' seconds'); } /** - * @param Document $document certificates document + * @param Document $document certificates document + * * @throws \Utopia\Database\Exception\Authorization */ protected function deleteCertificates(Document $document): void @@ -843,10 +855,10 @@ class DeletesV1 extends Worker // If domain has certificate generated if (isset($document['certificateId'])) { $domainUsingCertificate = $consoleDB->findOne('domains', [ - Query::equal('certificateId', [$document['certificateId']]) + Query::equal('certificateId', [$document['certificateId']]), ]); - if (!$domainUsingCertificate) { + if (! $domainUsingCertificate) { $mainDomain = App::getEnv('_APP_DOMAIN_TARGET', ''); if ($mainDomain === $document->getAttribute('domain')) { $domainUsingCertificate = $mainDomain; @@ -856,13 +868,14 @@ class DeletesV1 extends Worker // If certificate is still used by some domain, mark we can't delete. // Current domain should not be found, because we only have copy. Original domain is already deleted from database. if ($domainUsingCertificate) { - Console::warning("Skipping certificate deletion, because a domain is still using it."); + Console::warning('Skipping certificate deletion, because a domain is still using it.'); + return; } } $domain = $document->getAttribute('domain'); - $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; + $directory = APP_STORAGE_CERTIFICATES.'/'.$domain; $checkTraversal = realpath($directory) === $directory; if ($domain && $checkTraversal && is_dir($directory)) { @@ -872,7 +885,7 @@ class DeletesV1 extends Worker } // Delete files, so Traefik is aware of change - array_map('unlink', glob($directory . '/*.*')); + array_map('unlink', glob($directory.'/*.*')); rmdir($directory); Console::info("Deleted certificate files for {$domain}"); } else { @@ -884,7 +897,7 @@ class DeletesV1 extends Worker { $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); - $dbForProject->deleteCollection('bucket_' . $document->getInternalId()); + $dbForProject->deleteCollection('bucket_'.$document->getInternalId()); $device = $this->getFilesDevice($projectId); diff --git a/app/workers/functions.php b/app/workers/functions.php index 7dec0ce90c..d5aab70534 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -1,11 +1,10 @@ getAttribute('runtime'), $runtimes)) { - throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + if (! \array_key_exists($function->getAttribute('runtime'), $runtimes)) { + throw new Exception('Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); } $runtime = $runtimes[$function->getAttribute('runtime')]; @@ -109,7 +109,6 @@ Server::setResource('execute', function () { /** * Usage */ - $queueForUsage ->addMetric(METRIC_EXECUTIONS, 1) // per project ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1); // per function @@ -120,6 +119,7 @@ Server::setResource('execute', function () { $vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) { $carry[$var->getAttribute('key')] = $var->getAttribute('value'); + return $carry; }, []); @@ -164,7 +164,7 @@ Server::setResource('execute', function () { } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); $execution - ->setAttribute('duration', (float)$interval->format('%s.%f')) + ->setAttribute('duration', (float) $interval->format('%s.%f')) ->setAttribute('status', 'failed') ->setAttribute('statusCode', $th->getCode()) ->setAttribute('stderr', $th->getMessage()); @@ -195,7 +195,7 @@ Server::setResource('execute', function () { /** Trigger realtime event */ $allEvents = Event::generateEvents('functions.[functionId].executions.[executionId].update', [ 'functionId' => $function->getId(), - 'executionId' => $execution->getId() + 'executionId' => $execution->getId(), ]); $target = Realtime::fromPayload( // Pass first, most verbose event pattern @@ -220,10 +220,9 @@ Server::setResource('execute', function () { /** Trigger usage queue */ $queueForUsage ->setProject($project) - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) - ->trigger() - ; + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int) ($execution->getAttribute('duration') * 1000))// per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int) ($execution->getAttribute('duration') * 1000)) + ->trigger(); }; }); @@ -253,7 +252,7 @@ $server->job() return; } - if (!empty($events)) { + if (! empty($events)) { $limit = 30; $sum = 30; $offset = 0; @@ -262,19 +261,19 @@ $server->job() while ($sum >= $limit) { $functions = $dbForProject->find('functions', [ Query::limit($limit), - Query::offset($offset) + Query::offset($offset), ]); $sum = \count($functions); $offset = $offset + $limit; - Console::log('Fetched ' . $sum . ' functions...'); + Console::log('Fetched '.$sum.' functions...'); foreach ($functions as $function) { - if (!array_intersect($events, $function->getAttribute('events', []))) { + if (! array_intersect($events, $function->getAttribute('events', []))) { continue; } - Console::success('Iterating function: ' . $function->getAttribute('name')); + Console::success('Iterating function: '.$function->getAttribute('name')); try { $execute( log: $log, @@ -291,12 +290,13 @@ $server->job() executionId: null, jwt: null ); - Console::success('Triggered function: ' . $events[0]); + Console::success('Triggered function: '.$events[0]); } catch (\Throwable $th) { - Console::error("Failed to execute " . $function->getId() . " with error: " . $th->getMessage()); + Console::error('Failed to execute '.$function->getId().' with error: '.$th->getMessage()); } } } + return; } diff --git a/app/workers/mails.php b/app/workers/mails.php index e1ce8307ac..d8949c0222 100644 --- a/app/workers/mails.php +++ b/app/workers/mails.php @@ -1,20 +1,20 @@ args['recipient']; $subject = $this->args['subject']; $name = $this->args['name']; @@ -49,7 +49,7 @@ class MailsV1 extends Worker $mail->clearBCCs(); $mail->clearCCs(); - $mail->setFrom(App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), (empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')) : $from)); + $mail->setFrom(App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), (empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')) : $from)); $mail->addAddress($recipient, $name); if (isset($smtp['replyTo'])) { $mail->addReplyTo($smtp['replyTo']); @@ -61,7 +61,7 @@ class MailsV1 extends Worker try { $mail->send(); } catch (\Exception $error) { - throw new Exception('Error sending mail: ' . $error->getMessage(), 500); + throw new Exception('Error sending mail: '.$error->getMessage(), 500); } } @@ -77,14 +77,14 @@ class MailsV1 extends Worker $mail->XMailer = 'Appwrite Mailer'; $mail->Host = $smtp['host']; $mail->Port = $smtp['port']; - $mail->SMTPAuth = (!empty($username) && !empty($password)); + $mail->SMTPAuth = (! empty($username) && ! empty($password)); $mail->Username = $username; $mail->Password = $password; $mail->SMTPSecure = $smtp['secure'] === 'tls'; $mail->SMTPAutoTLS = false; $mail->CharSet = 'UTF-8'; - $from = \urldecode($smtp['senderName'] ?? App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); + $from = \urldecode($smtp['senderName'] ?? App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')); $email = $smtp['senderEmail'] ?? App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $mail->setFrom($email, $from); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 84af6fa802..b826dc1c3f 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -2,41 +2,43 @@ use Appwrite\Resque\Worker; use Utopia\CLI\Console; +use Utopia\Messaging\Adapters\Email as EmailAdapter; +use Utopia\Messaging\Adapters\Email\Mailgun; +use Utopia\Messaging\Adapters\Email\SendGrid; +use Utopia\Messaging\Adapters\Push\APNS; +use Utopia\Messaging\Adapters\Push as PushAdapter; +use Utopia\Messaging\Adapters\Push\FCM; use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Adapters\SMS\Msg91; use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; use Utopia\Messaging\Adapters\SMS\Twilio; use Utopia\Messaging\Adapters\SMS\Vonage; -use Utopia\Messaging\Adapters\Push as PushAdapter; -use Utopia\Messaging\Adapters\Push\APNS; -use Utopia\Messaging\Adapters\Push\FCM; -use Utopia\Messaging\Adapters\Email as EmailAdapter; -use Utopia\Messaging\Adapters\Email\Mailgun; -use Utopia\Messaging\Adapters\Email\SendGrid; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Messaging V1 Worker'); -Console::success(APP_NAME . ' messaging worker v1 has started' . "\n"); +Console::success(APP_NAME.' messaging worker v1 has started'."\n"); class MessagingV1 extends Worker { protected ?SMSAdapter $sms = null; - protected ?PushAdapter $push = null; - protected ?EmailAdapter $email = null; + protected ?PushAdapter $push = null; + + protected ?EmailAdapter $email = null; protected ?string $from = null; public function getName(): string { - return "mails"; + return 'mails'; } public function sms($record): ?SMSAdapter { $credentials = $record->getAttribute('credentials'); + return match ($record->getAttribute('provider')) { 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), @@ -50,6 +52,7 @@ class MessagingV1 extends Worker public function push($record): ?PushAdapter { $credentials = $record->getAttribute('credentials'); + return match ($record->getAttribute('provider')) { 'apns' => new APNS( $credentials['authKey'], @@ -66,6 +69,7 @@ class MessagingV1 extends Worker public function email($record): ?EmailAdapter { $credentials = $record->getAttribute('credentials'); + return match ($record->getAttribute('provider')) { 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain']), 'sendgrid' => new SendGrid($credentials['apiKey']), @@ -92,9 +96,9 @@ class MessagingV1 extends Worker default => null }; - // Query for the provider - // switch on provider name - // call function passing needed credentials returns required provider. + // Query for the provider + // switch on provider name + // call function passing needed credentials returns required provider. $messageId = $this->args['messageId']; $messageRecord = @@ -109,7 +113,6 @@ class MessagingV1 extends Worker default => null }; - $provider->send($message); } @@ -141,7 +144,7 @@ class MessagingV1 extends Worker return [ 'from' => $from, 'to' => $to, - 'body' => $body + 'body' => $body, ]; } @@ -156,7 +159,7 @@ class MessagingV1 extends Worker 'to' => $to, 'title' => $title, 'body' => $body, - 'data' => $data + 'data' => $data, ]; } } diff --git a/app/workers/migrations.php b/app/workers/migrations.php index 0f8194acf8..99529d4fb2 100644 --- a/app/workers/migrations.php +++ b/app/workers/migrations.php @@ -18,10 +18,10 @@ use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; use Utopia\Migration\Transfer; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Migrations V1 Worker'); -Console::success(APP_NAME . ' Migrations worker v1 has started'); +Console::success(APP_NAME.' Migrations worker v1 has started'); class MigrationsV1 extends Worker { diff --git a/app/workers/usage.php b/app/workers/usage.php index 0c9dcbc5aa..3e76d8e8e7 100644 --- a/app/workers/usage.php +++ b/app/workers/usage.php @@ -1,17 +1,17 @@ setNamespace('_' . $projectInternalId); + $dbForProject->setNamespace('_'.$projectInternalId); switch (true) { case $document->getCollection() === 'users': // users $sessions = count($document->getAttribute(METRIC_SESSIONS, 0)); - if (!empty($sessions)) { + if (! empty($sessions)) { $metrics[] = [ 'key' => METRIC_SESSIONS, 'value' => ($sessions * -1), @@ -55,28 +55,28 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); - if (!empty($collections['value'])) { + $collections = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); + if (! empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, 'value' => ($collections['value'] * -1), ]; } - if (!empty($documents['value'])) { + if (! empty($documents['value'])) { $metrics[] = [ 'key' => METRIC_DOCUMENTS, 'value' => ($documents['value'] * -1), ]; } break; - case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections + case str_starts_with($document->getCollection(), 'database_') && ! str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; - $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); + $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); - if (!empty($documents['value'])) { + if (! empty($documents['value'])) { $metrics[] = [ 'key' => METRIC_DOCUMENTS, 'value' => ($documents['value'] * -1), @@ -89,17 +89,17 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); - if (!empty($files['value'])) { + if (! empty($files['value'])) { $metrics[] = [ 'key' => METRIC_FILES, 'value' => ($files['value'] * -1), ]; } - if (!empty($storage['value'])) { + if (! empty($storage['value'])) { $metrics[] = [ 'key' => METRIC_FILES_STORAGE, 'value' => ($storage['value'] * -1), @@ -108,57 +108,57 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools break; case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); - if (!empty($deployments['value'])) { + if (! empty($deployments['value'])) { $metrics[] = [ 'key' => METRIC_DEPLOYMENTS, 'value' => ($deployments['value'] * -1), ]; } - if (!empty($deploymentsStorage['value'])) { + if (! empty($deploymentsStorage['value'])) { $metrics[] = [ 'key' => METRIC_DEPLOYMENTS_STORAGE, 'value' => ($deploymentsStorage['value'] * -1), ]; } - if (!empty($builds['value'])) { + if (! empty($builds['value'])) { $metrics[] = [ 'key' => METRIC_BUILDS, 'value' => ($builds['value'] * -1), ]; } - if (!empty($buildsStorage['value'])) { + if (! empty($buildsStorage['value'])) { $metrics[] = [ 'key' => METRIC_BUILDS_STORAGE, 'value' => ($buildsStorage['value'] * -1), ]; } - if (!empty($buildsCompute['value'])) { + if (! empty($buildsCompute['value'])) { $metrics[] = [ 'key' => METRIC_BUILDS_COMPUTE, 'value' => ($buildsCompute['value'] * -1), ]; } - if (!empty($executions['value'])) { + if (! empty($executions['value'])) { $metrics[] = [ 'key' => METRIC_EXECUTIONS, 'value' => ($executions['value'] * -1), ]; } - if (!empty($executionsCompute['value'])) { + if (! empty($executionsCompute['value'])) { $metrics[] = [ 'key' => METRIC_EXECUTIONS_COMPUTE, 'value' => ($executionsCompute['value'] * -1), @@ -169,20 +169,18 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools break; } } catch (\Exception $e) { - console::error("[reducer] " . " {DateTime::now()} " . " {$projectInternalId} " . " {$e->getMessage()}"); + console::error('[reducer] '.' {DateTime::now()} '." {$projectInternalId} "." {$e->getMessage()}"); } finally { $pools->reclaim(); } }; }, ['cache', 'register', 'pools']); - $server->job() ->inject('message') ->inject('reduce') ->action(function (Message $message, callable $reduce) use (&$stats) { - $payload = $message->getPayload() ?? []; $project = new Document($payload['project'] ?? []); $projectId = $project->getInternalId(); @@ -191,18 +189,19 @@ $server->job() continue; } - $reduce( - database: $project->getAttribute('database'), - projectInternalId: $project->getInternalId(), - document: new Document($document), - metrics: $payload['metrics'], - ); + $reduce( + database: $project->getAttribute('database'), + projectInternalId: $project->getInternalId(), + document: new Document($document), + metrics: $payload['metrics'], + ); } $stats[$projectId]['database'] = $project->getAttribute('database'); foreach ($payload['metrics'] ?? [] as $metric) { - if (!isset($stats[$projectId]['keys'][$metric['key']])) { + if (! isset($stats[$projectId]['keys'][$metric['key']])) { $stats[$projectId]['keys'][$metric['key']] = $metric['value']; + continue; } $stats[$projectId]['keys'][$metric['key']] += $metric['value']; @@ -215,8 +214,7 @@ $server ->inject('cache') ->inject('pools') ->action(function ($register, $cache, $pools) use ($periods, &$stats) { - Timer::tick(30000, function () use ($register, $cache, $pools, $periods, &$stats) { - + Timer::tick(30000, function () use ($cache, $pools, $periods, &$stats) { $offset = count($stats); $projects = array_slice($stats, 0, $offset, true); array_splice($stats, 0, $offset); @@ -231,7 +229,7 @@ $server $cache ); - $dbForProject->setNamespace('_' . $projectInternalId); + $dbForProject->setNamespace('_'.$projectInternalId); foreach ($project['keys'] ?? [] as $key => $value) { if ($value == 0) { @@ -270,7 +268,7 @@ $server } } } - if (!empty($project['keys'])) { + if (! empty($project['keys'])) { $dbForProject->createDocument('statsLogger', new Document([ 'time' => DateTime::now(), 'metrics' => $project['keys'], @@ -278,7 +276,7 @@ $server } } catch (\Exception $e) { $now = DateTime::now(); - console::error("[Error] " . " Time: {$now} " . " projectInternalId: {$projectInternalId}" . " File: {$e->getFile()}" . " Line: {$e->getLine()} " . " message: {$e->getMessage()}"); + console::error('[Error] '." Time: {$now} "." projectInternalId: {$projectInternalId}"." File: {$e->getFile()}"." Line: {$e->getLine()} "." message: {$e->getMessage()}"); } finally { $pools->reclaim(); } diff --git a/app/workers/webhooks.php b/app/workers/webhooks.php index 4048581c0c..33fd4e5f6c 100644 --- a/app/workers/webhooks.php +++ b/app/workers/webhooks.php @@ -5,10 +5,10 @@ use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Document; -require_once __DIR__ . '/../init.php'; +require_once __DIR__.'/../init.php'; Console::title('Webhooks V1 Worker'); -Console::success(APP_NAME . ' webhooks worker v1 has started'); +Console::success(APP_NAME.' webhooks worker v1 has started'); class WebhooksV1 extends Worker { @@ -16,7 +16,7 @@ class WebhooksV1 extends Worker public function getName(): string { - return "webhooks"; + return 'webhooks'; } public function init(): void @@ -36,7 +36,7 @@ class WebhooksV1 extends Worker } } - if (!empty($this->errors)) { + if (! empty($this->errors)) { throw new Exception(\implode(" / \n\n", $this->errors)); } } @@ -45,7 +45,7 @@ class WebhooksV1 extends Worker { $url = \rawurldecode($webhook->getAttribute('url')); $signatureKey = $webhook->getAttribute('signatureKey'); - $signature = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $signature = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $httpUser = $webhook->getAttribute('httpUser'); $httpPass = $webhook->getAttribute('httpPass'); $ch = \curl_init($webhook->getAttribute('url')); @@ -64,28 +64,28 @@ class WebhooksV1 extends Worker CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', - 'Content-Length: ' . \strlen($payload), - 'X-' . APP_NAME . '-Webhook-Id: ' . $webhook->getId(), - 'X-' . APP_NAME . '-Webhook-Events: ' . implode(',', $events), - 'X-' . APP_NAME . '-Webhook-Name: ' . $webhook->getAttribute('name', ''), - 'X-' . APP_NAME . '-Webhook-User-Id: ' . $user->getId(), - 'X-' . APP_NAME . '-Webhook-Project-Id: ' . $project->getId(), - 'X-' . APP_NAME . '-Webhook-Signature: ' . $signature, + 'Content-Length: '.\strlen($payload), + 'X-'.APP_NAME.'-Webhook-Id: '.$webhook->getId(), + 'X-'.APP_NAME.'-Webhook-Events: '.implode(',', $events), + 'X-'.APP_NAME.'-Webhook-Name: '.$webhook->getAttribute('name', ''), + 'X-'.APP_NAME.'-Webhook-User-Id: '.$user->getId(), + 'X-'.APP_NAME.'-Webhook-Project-Id: '.$project->getId(), + 'X-'.APP_NAME.'-Webhook-Signature: '.$signature, ] ); - if (!$webhook->getAttribute('security', true)) { + if (! $webhook->getAttribute('security', true)) { \curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); \curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - if (!empty($httpUser) && !empty($httpPass)) { + if (! empty($httpUser) && ! empty($httpPass)) { \curl_setopt($ch, CURLOPT_USERPWD, "$httpUser:$httpPass"); \curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); } if (false === \curl_exec($ch)) { - $this->errors[] = \curl_error($ch) . ' in events ' . implode(', ', $events) . ' for webhook ' . $webhook->getAttribute('name'); + $this->errors[] = \curl_error($ch).' in events '.implode(', ', $events).' for webhook '.$webhook->getAttribute('name'); } \curl_close($ch); diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index e97c271ae2..98a0cf27d8 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -9,8 +9,8 @@ use Appwrite\Auth\Hash\Phpass; use Appwrite\Auth\Hash\Scrypt; use Appwrite\Auth\Hash\Scryptmodified; use Appwrite\Auth\Hash\Sha; -use Utopia\Database\Document; use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; @@ -25,49 +25,69 @@ class Auth 'phpass', 'scrypt', 'scryptMod', - 'plaintext' + 'plaintext', ]; public const DEFAULT_ALGO = 'argon2'; + public const DEFAULT_ALGO_OPTIONS = ['type' => 'argon2', 'memoryCost' => 2048, 'timeCost' => 4, 'threads' => 3]; /** * User Roles. */ public const USER_ROLE_ANY = 'any'; + public const USER_ROLE_GUESTS = 'guests'; + public const USER_ROLE_USERS = 'users'; + public const USER_ROLE_ADMIN = 'admin'; + public const USER_ROLE_DEVELOPER = 'developer'; + public const USER_ROLE_OWNER = 'owner'; + public const USER_ROLE_APPS = 'apps'; + public const USER_ROLE_SYSTEM = 'system'; /** * Token Types. */ public const TOKEN_TYPE_LOGIN = 1; // Deprecated + public const TOKEN_TYPE_VERIFICATION = 2; + public const TOKEN_TYPE_RECOVERY = 3; + public const TOKEN_TYPE_INVITE = 4; + public const TOKEN_TYPE_MAGIC_URL = 5; + public const TOKEN_TYPE_PHONE = 6; /** * Session Providers. */ public const SESSION_PROVIDER_EMAIL = 'email'; + public const SESSION_PROVIDER_ANONYMOUS = 'anonymous'; + public const SESSION_PROVIDER_MAGIC_URL = 'magic-url'; + public const SESSION_PROVIDER_PHONE = 'phone'; /** * Token Expiration times. */ public const TOKEN_EXPIRATION_LOGIN_LONG = 31536000; /* 1 year */ + public const TOKEN_EXPIRATION_LOGIN_SHORT = 3600; /* 1 hour */ + public const TOKEN_EXPIRATION_RECOVERY = 3600; /* 1 hour */ + public const TOKEN_EXPIRATION_CONFIRM = 3600 * 24 * 7; /* 7 days */ + public const TOKEN_EXPIRATION_PHONE = 60 * 15; /* 15 minutes */ /** @@ -93,7 +113,6 @@ class Auth * Set Cookie Name. * * @param $string - * * @return string */ public static function setCookieName($string) @@ -104,9 +123,8 @@ class Auth /** * Encode Session. * - * @param string $id - * @param string $secret - * + * @param string $id + * @param string $secret * @return string */ public static function encodeSession($id, $secret) @@ -120,8 +138,7 @@ class Auth /** * Decode Session. * - * @param string $session - * + * @param string $session * @return array * * @throws \Exception @@ -131,7 +148,7 @@ class Auth $session = \json_decode(\base64_decode($session), true); $default = ['id' => null, 'secret' => '']; - if (!\is_array($session)) { + if (! \is_array($session)) { return $default; } @@ -144,7 +161,6 @@ class Auth * One-way encryption * * @param $string - * * @return string */ public static function hash(string $string) @@ -157,10 +173,9 @@ class Auth * * One way string hashing for user passwords * - * @param string $string - * @param string $algo hashing algorithm to use - * @param array $options algo-specific options - * + * @param string $string + * @param string $algo hashing algorithm to use + * @param array $options algo-specific options * @return bool|string|null */ public static function passwordHash(string $string, string $algo, array $options = []) @@ -171,45 +186,51 @@ class Auth $options = Auth::DEFAULT_ALGO_OPTIONS; } - if (!\in_array($algo, Auth::SUPPORTED_ALGOS)) { - throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); + if (! \in_array($algo, Auth::SUPPORTED_ALGOS)) { + throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); } switch ($algo) { case 'argon2': $hasher = new Argon2($options); + return $hasher->hash($string); case 'bcrypt': $hasher = new Bcrypt($options); + return $hasher->hash($string); case 'md5': $hasher = new Md5($options); + return $hasher->hash($string); case 'sha': $hasher = new Sha($options); + return $hasher->hash($string); case 'phpass': $hasher = new Phpass($options); + return $hasher->hash($string); case 'scrypt': $hasher = new Scrypt($options); + return $hasher->hash($string); case 'scryptMod': $hasher = new Scryptmodified($options); + return $hasher->hash($string); default: - throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); + throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); } } /** * Password verify. * - * @param string $plain - * @param string $hash - * @param string $algo hashing algorithm used to hash - * @param array $options algo-specific options - * + * @param string $plain + * @param string $hash + * @param string $algo hashing algorithm used to hash + * @param array $options algo-specific options * @return bool */ public static function passwordVerify(string $plain, string $hash, string $algo, array $options = []) @@ -220,34 +241,41 @@ class Auth $options = Auth::DEFAULT_ALGO_OPTIONS; } - if (!\in_array($algo, Auth::SUPPORTED_ALGOS)) { - throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); + if (! \in_array($algo, Auth::SUPPORTED_ALGOS)) { + throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); } switch ($algo) { case 'argon2': $hasher = new Argon2($options); + return $hasher->verify($plain, $hash); case 'bcrypt': $hasher = new Bcrypt($options); + return $hasher->verify($plain, $hash); case 'md5': $hasher = new Md5($options); + return $hasher->verify($plain, $hash); case 'sha': $hasher = new Sha($options); + return $hasher->verify($plain, $hash); case 'phpass': $hasher = new Phpass($options); + return $hasher->verify($plain, $hash); case 'scrypt': $hasher = new Scrypt($options); + return $hasher->verify($plain, $hash); case 'scryptMod': $hasher = new Scryptmodified($options); + return $hasher->verify($plain, $hash); default: - throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); + throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); } } @@ -256,8 +284,7 @@ class Auth * * Generate random password string * - * @param int $length - * + * @param int $length * @return string */ public static function passwordGenerator(int $length = 20): string @@ -270,8 +297,7 @@ class Auth * * Generate random password string * - * @param int $length - * + * @param int $length * @return string */ public static function tokenGenerator(int $length = 128): string @@ -284,8 +310,7 @@ class Auth * * Generate random code string * - * @param int $length - * + * @param int $length * @return string */ public static function codeGenerator(int $length = 6): string @@ -302,10 +327,9 @@ class Auth /** * Verify token and check that its not expired. * - * @param array $tokens - * @param int $type - * @param string $secret - * + * @param array $tokens + * @param int $type + * @param string $secret * @return bool|string */ public static function tokenVerify(array $tokens, int $type, string $secret) @@ -320,7 +344,7 @@ class Auth $token->getAttribute('secret') === self::hash($secret) && DateTime::formatTz($token->getAttribute('expire')) >= DateTime::formatTz(DateTime::now()) ) { - return (string)$token->getId(); + return (string) $token->getId(); } } @@ -349,10 +373,9 @@ class Auth /** * Verify session and check that its not expired. * - * @param array $sessions - * @param string $secret - * @param string $expires - * + * @param array $sessions + * @param string $secret + * @param string $expires * @return bool|string */ public static function sessionVerify(array $sessions, string $secret, int $expires) @@ -375,8 +398,7 @@ class Auth /** * Is Privileged User? * - * @param array $roles - * + * @param array $roles * @return bool */ public static function isPrivilegedUser(array $roles): bool @@ -395,8 +417,7 @@ class Auth /** * Is App User? * - * @param array $roles - * + * @param array $roles * @return bool */ public static function isAppUser(array $roles): bool @@ -411,14 +432,14 @@ class Auth /** * Returns all roles for a user. * - * @param Document $user + * @param Document $user * @return array */ public static function getRoles(Document $user): array { $roles = []; - if (!self::isPrivilegedUser(Authorization::getRoles()) && !self::isAppUser(Authorization::getRoles())) { + if (! self::isPrivilegedUser(Authorization::getRoles()) && ! self::isAppUser(Authorization::getRoles())) { if ($user->getId()) { $roles[] = Role::user($user->getId())->toString(); $roles[] = Role::users()->toString(); @@ -439,7 +460,7 @@ class Auth } foreach ($user->getAttribute('memberships', []) as $node) { - if (!isset($node['confirm']) || !$node['confirm']) { + if (! isset($node['confirm']) || ! $node['confirm']) { continue; } @@ -456,7 +477,7 @@ class Auth } foreach ($user->getAttribute('labels', []) as $label) { - $roles[] = 'label:' . $label; + $roles[] = 'label:'.$label; } return $roles; diff --git a/src/Appwrite/Auth/Hash.php b/src/Appwrite/Auth/Hash.php index 7134057581..caf4771fcd 100644 --- a/src/Appwrite/Auth/Hash.php +++ b/src/Appwrite/Auth/Hash.php @@ -5,13 +5,13 @@ namespace Appwrite\Auth; abstract class Hash { /** - * @var array $options Hashing-algo specific options - */ + * @var array Hashing-algo specific options + */ protected array $options = []; /** - * @param array $options Hashing-algo specific options - */ + * @param array $options Hashing-algo specific options + */ public function __construct(array $options = []) { $this->setOptions($options); @@ -20,11 +20,12 @@ abstract class Hash /** * Set hashing algo options * - * @param array $options Hashing-algo specific options - */ + * @param array $options Hashing-algo specific options + */ public function setOptions(array $options): self { $this->options = \array_merge([], $this->getDefaultOptions(), $options); + return $this; } @@ -32,24 +33,22 @@ abstract class Hash * Get hashing algo options * * @return array $options Hashing-algo specific options - */ + */ public function getOptions(): array { return $this->options; } /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ abstract public function hash(string $password): string; /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ abstract public function verify(string $password, string $hash): bool; diff --git a/src/Appwrite/Auth/Hash/Argon2.php b/src/Appwrite/Auth/Hash/Argon2.php index c723b077b1..0e9c2fcf36 100644 --- a/src/Appwrite/Auth/Hash/Argon2.php +++ b/src/Appwrite/Auth/Hash/Argon2.php @@ -15,8 +15,7 @@ use Appwrite\Auth\Hash; class Argon2 extends Hash { /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -25,10 +24,9 @@ class Argon2 extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { diff --git a/src/Appwrite/Auth/Hash/Bcrypt.php b/src/Appwrite/Auth/Hash/Bcrypt.php index 8b6177f33a..c54cf3d452 100644 --- a/src/Appwrite/Auth/Hash/Bcrypt.php +++ b/src/Appwrite/Auth/Hash/Bcrypt.php @@ -14,8 +14,7 @@ use Appwrite\Auth\Hash; class Bcrypt extends Hash { /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -24,10 +23,9 @@ class Bcrypt extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -41,6 +39,6 @@ class Bcrypt extends Hash */ public function getDefaultOptions(): array { - return [ 'cost' => 8 ]; + return ['cost' => 8]; } } diff --git a/src/Appwrite/Auth/Hash/Md5.php b/src/Appwrite/Auth/Hash/Md5.php index 8ade3dd5e2..0f6fe5c30d 100644 --- a/src/Appwrite/Auth/Hash/Md5.php +++ b/src/Appwrite/Auth/Hash/Md5.php @@ -12,8 +12,7 @@ use Appwrite\Auth\Hash; class Md5 extends Hash { /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -22,10 +21,9 @@ class Md5 extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { diff --git a/src/Appwrite/Auth/Hash/Phpass.php b/src/Appwrite/Auth/Hash/Phpass.php index 187e4a27a6..ded4e407ff 100644 --- a/src/Appwrite/Auth/Hash/Phpass.php +++ b/src/Appwrite/Auth/Hash/Phpass.php @@ -39,6 +39,7 @@ class Phpass extends Hash * Alphabet used in itoa64 conversions. * * @var string + * * @since 0.1.0 */ protected string $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; @@ -59,8 +60,7 @@ class Phpass extends Hash } /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -68,7 +68,7 @@ class Phpass extends Hash $options = $this->getDefaultOptions(); $random = ''; - if (CRYPT_BLOWFISH === 1 && !$options['portable_hashes']) { + if (CRYPT_BLOWFISH === 1 && ! $options['portable_hashes']) { $random = $this->getRandomBytes(16, $options); $hash = crypt($password, $this->gensaltBlowfish($random, $options)); if (strlen($hash) === 60) { @@ -92,10 +92,9 @@ class Phpass extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -114,15 +113,16 @@ class Phpass extends Hash } /** - * @param int $count + * @param int $count + * @return string $output * - * @return String $output * @since 0.1.0 + * * @throws Exception Thows an Exception if the $count parameter is not a positive integer. */ protected function getRandomBytes(int $count, array $options): string { - if (!is_int($count) || $count < 1) { + if (! is_int($count) || $count < 1) { throw new \Exception('Argument count must be a positive integer'); } $output = ''; @@ -135,7 +135,7 @@ class Phpass extends Hash $output = ''; for ($i = 0; $i < $count; $i += 16) { - $options['iteration_count_log2'] = md5(microtime() . $options['iteration_count_log2']); + $options['iteration_count_log2'] = md5(microtime().$options['iteration_count_log2']); $output .= md5($options['iteration_count_log2'], true); } @@ -146,47 +146,48 @@ class Phpass extends Hash } /** - * @param String $input - * @param int $count + * @param string $input + * @param int $count + * @return string $output * - * @return String $output * @since 0.1.0 + * * @throws Exception Thows an Exception if the $count parameter is not a positive integer. */ protected function encode64($input, $count) { - if (!is_int($count) || $count < 1) { + if (! is_int($count) || $count < 1) { throw new \Exception('Argument count must be a positive integer'); } $output = ''; $i = 0; do { $value = ord($input[$i++]); - $output .= $this->itoa64[$value & 0x3f]; + $output .= $this->itoa64[$value & 0x3F]; if ($i < $count) { $value |= ord($input[$i]) << 8; } - $output .= $this->itoa64[($value >> 6) & 0x3f]; + $output .= $this->itoa64[($value >> 6) & 0x3F]; if ($i++ >= $count) { break; } if ($i < $count) { $value |= ord($input[$i]) << 16; } - $output .= $this->itoa64[($value >> 12) & 0x3f]; + $output .= $this->itoa64[($value >> 12) & 0x3F]; if ($i++ >= $count) { break; } - $output .= $this->itoa64[($value >> 18) & 0x3f]; + $output .= $this->itoa64[($value >> 18) & 0x3F]; } while ($i < $count); return $output; } /** - * @param String $input + * @param string $input + * @return string $output * - * @return String $output * @since 0.1.0 */ private function gensaltPrivate($input, $options) @@ -199,10 +200,10 @@ class Phpass extends Hash } /** - * @param String $password - * @param String $setting + * @param string $password + * @param string $setting + * @return string $output * - * @return String $output * @since 0.1.0 */ private function cryptPrivate($password, $setting) @@ -233,9 +234,9 @@ class Phpass extends Hash * consequently in lower iteration counts and hashes that are * quicker to crack (by non-PHP code). */ - $hash = md5($salt . $password, true); + $hash = md5($salt.$password, true); do { - $hash = md5($hash . $password, true); + $hash = md5($hash.$password, true); } while (--$count); $output = substr($setting, 0, 12); $output .= $this->encode64($hash, 16); @@ -244,9 +245,9 @@ class Phpass extends Hash } /** - * @param String $input + * @param string $input + * @return string $output * - * @return String $output * @since 0.1.0 */ private function gensaltBlowfish($input, $options) @@ -278,11 +279,11 @@ class Phpass extends Hash $c2 = ord($input[$i++]); $c1 |= $c2 >> 4; $output .= $itoa64[$c1]; - $c1 = ($c2 & 0x0f) << 2; + $c1 = ($c2 & 0x0F) << 2; $c2 = ord($input[$i++]); $c1 |= $c2 >> 6; $output .= $itoa64[$c1]; - $output .= $itoa64[$c2 & 0x3f]; + $output .= $itoa64[$c2 & 0x3F]; } while (1); return $output; diff --git a/src/Appwrite/Auth/Hash/Scrypt.php b/src/Appwrite/Auth/Hash/Scrypt.php index 821b1fba69..8c50c16341 100644 --- a/src/Appwrite/Auth/Hash/Scrypt.php +++ b/src/Appwrite/Auth/Hash/Scrypt.php @@ -17,8 +17,7 @@ use Appwrite\Auth\Hash; class Scrypt extends Hash { /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -29,10 +28,9 @@ class Scrypt extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -46,6 +44,6 @@ class Scrypt extends Hash */ public function getDefaultOptions(): array { - return [ 'costCpu' => 8, 'costMemory' => 14, 'costParallel' => 1, 'length' => 64 ]; + return ['costCpu' => 8, 'costMemory' => 14, 'costParallel' => 1, 'length' => 64]; } } diff --git a/src/Appwrite/Auth/Hash/Scryptmodified.php b/src/Appwrite/Auth/Hash/Scryptmodified.php index 2d1cd4f165..9260913aed 100644 --- a/src/Appwrite/Auth/Hash/Scryptmodified.php +++ b/src/Appwrite/Auth/Hash/Scryptmodified.php @@ -16,8 +16,7 @@ use Appwrite\Auth\Hash; class Scryptmodified extends Hash { /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -33,10 +32,9 @@ class Scryptmodified extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -50,7 +48,7 @@ class Scryptmodified extends Hash */ public function getDefaultOptions(): array { - return [ ]; + return []; } private function generateDerivedKey(string $password) @@ -60,7 +58,7 @@ class Scryptmodified extends Hash $saltBytes = \base64_decode($options['salt']); $saltSeparatorBytes = \base64_decode($options['saltSeparator']); - $derivedKey = \scrypt(\utf8_encode($password), $saltBytes . $saltSeparatorBytes, 16384, 8, 1, 64); + $derivedKey = \scrypt(\utf8_encode($password), $saltBytes.$saltSeparatorBytes, 16384, 8, 1, 64); $derivedKey = \hex2bin($derivedKey); return $derivedKey; diff --git a/src/Appwrite/Auth/Hash/Sha.php b/src/Appwrite/Auth/Hash/Sha.php index c2ae3b52c1..331c4fe6f2 100644 --- a/src/Appwrite/Auth/Hash/Sha.php +++ b/src/Appwrite/Auth/Hash/Sha.php @@ -16,8 +16,7 @@ use Appwrite\Auth\Hash; class Sha extends Hash { /** - * @param string $password Input password to hash - * + * @param string $password Input password to hash * @return string hash */ public function hash(string $password): string @@ -28,10 +27,9 @@ class Sha extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * @return bool true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -45,6 +43,6 @@ class Sha extends Hash */ public function getDefaultOptions(): array { - return [ 'version' => 'sha3-512' ]; + return ['version' => 'sha3-512']; } } diff --git a/src/Appwrite/Auth/OAuth2.php b/src/Appwrite/Auth/OAuth2.php index c737e183f8..37f6416fb5 100644 --- a/src/Appwrite/Auth/OAuth2.php +++ b/src/Appwrite/Auth/OAuth2.php @@ -34,11 +34,11 @@ abstract class OAuth2 /** * OAuth2 constructor. * - * @param string $appId - * @param string $appSecret - * @param string $callback - * @param array $state - * @param array $scopes + * @param string $appId + * @param string $appSecret + * @param string $callback + * @param array $state + * @param array $scopes */ public function __construct(string $appId, string $appSecret, string $callback, array $state = [], array $scopes = []) { @@ -62,29 +62,25 @@ abstract class OAuth2 abstract public function getLoginURL(): string; /** - * @param string $code - * + * @param string $code * @return array */ abstract protected function getTokens(string $code): array; /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ abstract public function refreshTokens(string $refreshToken): array; /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ abstract public function getUserID(string $accessToken): string; /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ abstract public function getUserEmail(string $accessToken): string; @@ -92,28 +88,25 @@ abstract class OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ abstract public function isEmailVerified(string $accessToken): bool; /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ abstract public function getUserName(string $accessToken): string; /** * @param $scope - * * @return $this */ protected function addScope(string $scope): OAuth2 { // Add a scope to the scopes array if it isn't already present - if (!\in_array($scope, $this->scopes)) { + if (! \in_array($scope, $this->scopes)) { $this->scopes[] = $scope; } @@ -129,8 +122,7 @@ abstract class OAuth2 } /** - * @param string $code - * + * @param string $code * @return string */ public function getAccessToken(string $code): string @@ -141,8 +133,7 @@ abstract class OAuth2 } /** - * @param string $code - * + * @param string $code * @return string */ public function getRefreshToken(string $code): string @@ -153,8 +144,7 @@ abstract class OAuth2 } /** - * @param string $code - * + * @param string $code * @return string */ public function getAccessTokenExpiry(string $code): int @@ -169,7 +159,6 @@ abstract class OAuth2 // json_decoding /** * @param $state - * * @return array */ public function parseState(string $state) @@ -178,11 +167,10 @@ abstract class OAuth2 } /** - * @param string $method - * @param string $url - * @param array $headers - * @param string $payload - * + * @param string $method + * @param string $url + * @param array $headers + * @param string $payload * @return string */ protected function request(string $method, string $url = '', array $headers = [], string $payload = ''): string @@ -194,11 +182,11 @@ abstract class OAuth2 \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); \curl_setopt($ch, CURLOPT_USERAGENT, 'Appwrite OAuth2'); - if (!empty($payload)) { + if (! empty($payload)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); } - $headers[] = 'Content-length: ' . \strlen($payload); + $headers[] = 'Content-length: '.\strlen($payload); \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Send the request & save response to $response @@ -212,6 +200,6 @@ abstract class OAuth2 throw new Exception($response, $code); } - return (string)$response; + return (string) $response; } } diff --git a/src/Appwrite/Auth/OAuth2/Amazon.php b/src/Appwrite/Auth/OAuth2/Amazon.php index d1d2cb5a38..c2cdedf2f1 100644 --- a/src/Appwrite/Auth/OAuth2/Amazon.php +++ b/src/Appwrite/Auth/OAuth2/Amazon.php @@ -25,7 +25,7 @@ class Amazon extends OAuth2 * @var array */ protected array $scopes = [ - "profile" + 'profile', ]; /** @@ -37,8 +37,7 @@ class Amazon extends OAuth2 } /** - * @param string $state - * + * @param string $state * @return array */ public function parseState(string $state) @@ -46,24 +45,22 @@ class Amazon extends OAuth2 return \json_decode(\html_entity_decode($state), true); } - /** * @return string */ public function getLoginURL(): string { - return 'https://www.amazon.com/ap/oa?' . \http_build_query([ + return 'https://www.amazon.com/ap/oa?'.\http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), - 'redirect_uri' => $this->callback + 'redirect_uri' => $this->callback, ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -79,7 +76,7 @@ class Amazon extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -88,8 +85,7 @@ class Amazon extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -103,7 +99,7 @@ class Amazon extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken + 'refresh_token' => $refreshToken, ]) ), true); @@ -115,8 +111,7 @@ class Amazon extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -127,8 +122,7 @@ class Amazon extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -143,20 +137,18 @@ class Amazon extends OAuth2 * * If present, the email is verified. This was verfied through a manual Amazon sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -167,16 +159,16 @@ class Amazon extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://api.amazon.com/user/profile?access_token=' . \urlencode($accessToken)); + $user = $this->request('GET', 'https://api.amazon.com/user/profile?access_token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); } + return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Apple.php b/src/Appwrite/Auth/OAuth2/Apple.php index 2abf61c947..27f41543ae 100644 --- a/src/Appwrite/Auth/OAuth2/Apple.php +++ b/src/Appwrite/Auth/OAuth2/Apple.php @@ -24,8 +24,8 @@ class Apple extends OAuth2 * @var array */ protected array $scopes = [ - "name", - "email" + 'name', + 'email', ]; /** @@ -46,19 +46,18 @@ class Apple extends OAuth2 */ public function getLoginURL(): string { - return 'https://appleid.apple.com/auth/authorize?' . \http_build_query([ + return 'https://appleid.apple.com/auth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'response_type' => 'code', 'response_mode' => 'form_post', - 'scope' => \implode(' ', $this->getScopes()) + 'scope' => \implode(' ', $this->getScopes()), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -86,8 +85,7 @@ class Apple extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -116,8 +114,7 @@ class Apple extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -126,8 +123,7 @@ class Apple extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -140,8 +136,7 @@ class Apple extends OAuth2 * * @link https://developer.apple.com/forums/thread/121411 * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -154,15 +149,14 @@ class Apple extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string { if ( isset($this->claims['email']) && - !empty($this->claims['email']) && + ! empty($this->claims['email']) && isset($this->claims['email_verified']) && $this->claims['email_verified'] === 'true' ) { @@ -183,7 +177,7 @@ class Apple extends OAuth2 $keyfile = (isset($secret['p8'])) ? $secret['p8'] : ''; // Your p8 Key file $keyID = (isset($secret['keyID'])) ? $secret['keyID'] : ''; // Your Key ID $teamID = (isset($secret['teamID'])) ? $secret['teamID'] : ''; // Your Team ID (see Developer Portal) - $bundleID = $this->appID; // Your Bundle ID + $bundleID = $this->appID; // Your Bundle ID $headers = [ 'alg' => 'ES256', @@ -200,22 +194,21 @@ class Apple extends OAuth2 $pkey = \openssl_pkey_get_private($keyfile); - $payload = $this->encode(\json_encode($headers)) . '.' . $this->encode(\json_encode($claims)); + $payload = $this->encode(\json_encode($headers)).'.'.$this->encode(\json_encode($claims)); $signature = ''; $success = \openssl_sign($payload, $signature, $pkey, OPENSSL_ALGO_SHA256); - if (!$success) { + if (! $success) { return ''; } - return $payload . '.' . $this->encode($this->fromDER($signature, 64)); + return $payload.'.'.$this->encode($this->fromDER($signature, 64)); } /** - * @param string $data - * + * @param string $data * @return string */ protected function encode($data): string @@ -224,7 +217,7 @@ class Apple extends OAuth2 } /** - * @param string $data + * @param string $data */ protected function retrievePositiveInteger(string $data): string { @@ -236,8 +229,8 @@ class Apple extends OAuth2 } /** - * @param string $der - * @param int $partLength + * @param string $der + * @param int $partLength */ protected function fromDER(string $der, int $partLength): string { @@ -270,6 +263,6 @@ class Apple extends OAuth2 $S = $this->retrievePositiveInteger(\mb_substr($hex, 4, $Sl * 2, '8bit')); $S = \str_pad($S, $partLength, '0', STR_PAD_LEFT); - return \pack('H*', $R . $S); + return \pack('H*', $R.$S); } } diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index eba7d18b5f..e2615017bd 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -16,7 +16,7 @@ class Auth0 extends OAuth2 'openid', 'profile', 'email', - 'offline_access' + 'offline_access', ]; /** @@ -42,18 +42,17 @@ class Auth0 extends OAuth2 */ public function getLoginURL(): string { - return 'https://' . $this->getAuth0Domain() . '/authorize?' . \http_build_query([ + return 'https://'.$this->getAuth0Domain().'/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -62,7 +61,7 @@ class Auth0 extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://' . $this->getAuth0Domain() . '/oauth/token', + 'https://'.$this->getAuth0Domain().'/oauth/token', $headers, \http_build_query([ 'code' => $code, @@ -70,7 +69,7 @@ class Auth0 extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -78,10 +77,8 @@ class Auth0 extends OAuth2 return $this->tokens; } - /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -89,13 +86,13 @@ class Auth0 extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://' . $this->getAuth0Domain() . '/oauth/token', + 'https://'.$this->getAuth0Domain().'/oauth/token', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -107,8 +104,7 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -119,8 +115,7 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -135,8 +130,7 @@ class Auth0 extends OAuth2 * * @link https://auth0.com/docs/api/authentication?javascript#user-profile * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -151,8 +145,7 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -163,15 +156,14 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; - $user = $this->request('GET', 'https://' . $this->getAuth0Domain() . '/userinfo', $headers); + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $user = $this->request('GET', 'https://'.$this->getAuth0Domain().'/userinfo', $headers); $this->user = \json_decode($user, true); } @@ -214,6 +206,7 @@ class Auth0 extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } + return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Authentik.php b/src/Appwrite/Auth/OAuth2/Authentik.php index 16822e2c9f..8a6b13cdef 100644 --- a/src/Appwrite/Auth/OAuth2/Authentik.php +++ b/src/Appwrite/Auth/OAuth2/Authentik.php @@ -16,7 +16,7 @@ class Authentik extends OAuth2 'openid', 'profile', 'email', - 'offline_access' + 'offline_access', ]; /** @@ -42,18 +42,17 @@ class Authentik extends OAuth2 */ public function getLoginURL(): string { - return 'https://' . $this->getAuthentikDomain() . '/application/o/authorize?' . \http_build_query([ + return 'https://'.$this->getAuthentikDomain().'/application/o/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -62,7 +61,7 @@ class Authentik extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://' . $this->getAuthentikDomain() . '/application/o/token/', + 'https://'.$this->getAuthentikDomain().'/application/o/token/', $headers, \http_build_query([ 'code' => $code, @@ -70,17 +69,16 @@ class Authentik extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } + return $this->tokens; } - /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -88,13 +86,13 @@ class Authentik extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://' . $this->getAuthentikDomain() . '/application/o/token/', + 'https://'.$this->getAuthentikDomain().'/application/o/token/', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -106,8 +104,7 @@ class Authentik extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -122,8 +119,7 @@ class Authentik extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -140,8 +136,7 @@ class Authentik extends OAuth2 /** * Check if the User email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -156,8 +151,7 @@ class Authentik extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -171,16 +165,15 @@ class Authentik extends OAuth2 return ''; } - /** - * @param string $accessToken - * + /** + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; - $user = $this->request('GET', 'https://' . $this->getAuthentikDomain() . '/application/o/userinfo/', $headers); + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $user = $this->request('GET', 'https://'.$this->getAuthentikDomain().'/application/o/userinfo/', $headers); $this->user = \json_decode($user, true); } @@ -199,7 +192,7 @@ class Authentik extends OAuth2 return $secret['clientSecret'] ?? ''; } - /** + /** * Extracts the authentik Domain from the JSON stored in appSecret * * @return string @@ -207,6 +200,7 @@ class Authentik extends OAuth2 protected function getAuthentikDomain(): string { $secret = $this->getAppSecret(); + return $secret['authentikDomain'] ?? ''; } @@ -222,6 +216,7 @@ class Authentik extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } + return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Autodesk.php b/src/Appwrite/Auth/OAuth2/Autodesk.php index 0b268ead3b..071eee7dcb 100644 --- a/src/Appwrite/Auth/OAuth2/Autodesk.php +++ b/src/Appwrite/Auth/OAuth2/Autodesk.php @@ -36,18 +36,17 @@ class Autodesk extends OAuth2 */ public function getLoginURL(): string { - return 'https://developer.api.autodesk.com/authentication/v1/authorize?' . \http_build_query([ + return 'https://developer.api.autodesk.com/authentication/v1/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), 'redirect_uri' => $this->callback, - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -63,7 +62,7 @@ class Autodesk extends OAuth2 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'code' => $code, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ); @@ -74,8 +73,7 @@ class Autodesk extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -105,8 +103,7 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -117,8 +114,7 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -133,8 +129,7 @@ class Autodesk extends OAuth2 * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -149,8 +144,7 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -161,14 +155,13 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; $user = $this->request('GET', 'https://developer.api.autodesk.com/userprofile/v1/users/@me', $headers); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Bitbucket.php b/src/Appwrite/Auth/OAuth2/Bitbucket.php index 361bc22b65..eea5af4c1b 100644 --- a/src/Appwrite/Auth/OAuth2/Bitbucket.php +++ b/src/Appwrite/Auth/OAuth2/Bitbucket.php @@ -37,7 +37,7 @@ class Bitbucket extends OAuth2 */ public function getLoginURL(): string { - return 'https://bitbucket.org/site/oauth2/authorize?' . \http_build_query([ + return 'https://bitbucket.org/site/oauth2/authorize?'.\http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), @@ -46,8 +46,7 @@ class Bitbucket extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -63,7 +62,7 @@ class Bitbucket extends OAuth2 'code' => $code, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -72,8 +71,7 @@ class Bitbucket extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -87,7 +85,7 @@ class Bitbucket extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken + 'refresh_token' => $refreshToken, ]) ), true); @@ -99,8 +97,7 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -111,8 +108,7 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -125,8 +121,7 @@ class Bitbucket extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -141,8 +136,7 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -153,17 +147,16 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://api.bitbucket.org/2.0/user?access_token=' . \urlencode($accessToken)); + $user = $this->request('GET', 'https://api.bitbucket.org/2.0/user?access_token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); - $emails = $this->request('GET', 'https://api.bitbucket.org/2.0/user/emails?access_token=' . \urlencode($accessToken)); + $emails = $this->request('GET', 'https://api.bitbucket.org/2.0/user/emails?access_token='.\urlencode($accessToken)); $emails = \json_decode($emails, true); if (isset($emails['values'])) { foreach ($emails['values'] as $email) { @@ -175,6 +168,7 @@ class Bitbucket extends OAuth2 } } } + return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Bitly.php b/src/Appwrite/Auth/OAuth2/Bitly.php index 290876a8cb..b5521cad39 100644 --- a/src/Appwrite/Auth/OAuth2/Bitly.php +++ b/src/Appwrite/Auth/OAuth2/Bitly.php @@ -47,17 +47,16 @@ class Bitly extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . 'authorize?' . + return $this->endpoint.'authorize?'. \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -65,14 +64,14 @@ class Bitly extends OAuth2 if (empty($this->tokens)) { $response = $this->request( 'POST', - $this->resourceEndpoint . 'oauth/access_token', - ["Content-Type: application/x-www-form-urlencoded"], + $this->resourceEndpoint.'oauth/access_token', + ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "code" => $code, - "redirect_uri" => $this->callback, - "state" => \json_encode($this->state) + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'code' => $code, + 'redirect_uri' => $this->callback, + 'state' => \json_encode($this->state), ]) ); @@ -85,21 +84,20 @@ class Bitly extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $response = $this->request( 'POST', - $this->resourceEndpoint . 'oauth/access_token', - ["Content-Type: application/x-www-form-urlencoded"], + $this->resourceEndpoint.'oauth/access_token', + ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "refresh_token" => $refreshToken, - 'grant_type' => 'refresh_token' + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'refresh_token' => $refreshToken, + 'grant_type' => 'refresh_token', ]) ); @@ -115,8 +113,7 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -127,8 +124,7 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -151,8 +147,7 @@ class Bitly extends OAuth2 * * @link https://dev.bitly.com/api-reference#getUser * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -161,8 +156,7 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -173,19 +167,18 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) { $headers = [ - 'Authorization: Bearer ' . \urlencode($accessToken), - "Accept: application/json" + 'Authorization: Bearer '.\urlencode($accessToken), + 'Accept: application/json', ]; if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', $this->resourceEndpoint . "v4/user", $headers), true); + $this->user = \json_decode($this->request('GET', $this->resourceEndpoint.'v4/user', $headers), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Box.php b/src/Appwrite/Auth/OAuth2/Box.php index e88c165833..5d2c5e2b38 100644 --- a/src/Appwrite/Auth/OAuth2/Box.php +++ b/src/Appwrite/Auth/OAuth2/Box.php @@ -49,7 +49,7 @@ class Box extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint . 'authorize?' . + $url = $this->endpoint.'authorize?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, @@ -62,8 +62,7 @@ class Box extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -72,15 +71,15 @@ class Box extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'token', + $this->endpoint.'token', $headers, \http_build_query([ - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "code" => $code, - "grant_type" => "authorization_code", - "scope" => \implode(',', $this->getScopes()), - "redirect_uri" => $this->callback + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'code' => $code, + 'grant_type' => 'authorization_code', + 'scope' => \implode(',', $this->getScopes()), + 'redirect_uri' => $this->callback, ]) ), true); } @@ -89,8 +88,7 @@ class Box extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -98,13 +96,13 @@ class Box extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'token', + $this->endpoint.'token', $headers, \http_build_query([ - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "refresh_token" => $refreshToken, - "grant_type" => "refresh_token", + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'refresh_token' => $refreshToken, + 'grant_type' => 'refresh_token', ]) ), true); @@ -116,8 +114,7 @@ class Box extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -128,8 +125,7 @@ class Box extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -144,20 +140,18 @@ class Box extends OAuth2 * * If present, the email is verified. This was verfied through a manual Box sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -168,19 +162,18 @@ class Box extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { $header = [ - 'Authorization: Bearer ' . \urlencode($accessToken), + 'Authorization: Bearer '.\urlencode($accessToken), ]; if (empty($this->user)) { $user = $this->request( 'GET', - $this->resourceEndpoint . 'me', + $this->resourceEndpoint.'me', $header ); $this->user = \json_decode($user, true); diff --git a/src/Appwrite/Auth/OAuth2/Dailymotion.php b/src/Appwrite/Auth/OAuth2/Dailymotion.php index 0fc90e3ca1..5ead308fbe 100644 --- a/src/Appwrite/Auth/OAuth2/Dailymotion.php +++ b/src/Appwrite/Auth/OAuth2/Dailymotion.php @@ -24,7 +24,7 @@ class Dailymotion extends OAuth2 */ protected array $scopes = [ 'userinfo', - 'email' + 'email', ]; /** @@ -34,7 +34,7 @@ class Dailymotion extends OAuth2 'email', 'id', 'fullname', - 'verified' + 'verified', ]; /** @@ -68,21 +68,20 @@ class Dailymotion extends OAuth2 */ public function getLoginURL(): string { - $url = $this->authEndpoint . '?' . + $url = $this->authEndpoint.'?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'state' => \json_encode($this->state), 'redirect_uri' => $this->callback, - 'scope' => \implode(' ', $this->getScopes()) + 'scope' => \implode(' ', $this->getScopes()), ]); return $url; } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -90,33 +89,31 @@ class Dailymotion extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', - ["Content-Type: application/x-www-form-urlencoded"], + $this->endpoint.'/oauth/token', + ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "redirect_uri" => $this->callback, + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'redirect_uri' => $this->callback, 'code' => $code, 'scope' => \implode(' ', $this->getScopes()), ]) ), true); } + return $this->tokens; } - /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { - $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -130,13 +127,11 @@ class Dailymotion extends OAuth2 $this->tokens['refresh_token'] = $refreshToken; } - return $this->tokens; } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -149,8 +144,7 @@ class Dailymotion extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -166,8 +160,7 @@ class Dailymotion extends OAuth2 * * @link https://developers.dailymotion.com/api/#user-fields * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -178,23 +171,20 @@ class Dailymotion extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string { $user = $this->getUser($accessToken); - $username = $user['fullname'] ?? ''; return $username; } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array @@ -202,8 +192,8 @@ class Dailymotion extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - $this->endpoint . '/user/me?fields=' . \implode(',', $this->getFields()), - ['Authorization: Bearer ' . \urlencode($accessToken)], + $this->endpoint.'/user/me?fields='.\implode(',', $this->getFields()), + ['Authorization: Bearer '.\urlencode($accessToken)], ); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Discord.php b/src/Appwrite/Auth/OAuth2/Discord.php index b77ce6a236..b98d5bdc0c 100644 --- a/src/Appwrite/Auth/OAuth2/Discord.php +++ b/src/Appwrite/Auth/OAuth2/Discord.php @@ -28,8 +28,8 @@ class Discord extends OAuth2 * @var array */ protected array $scopes = [ - 'identify', - 'email' + 'identify', + 'email', ]; /** @@ -45,21 +45,20 @@ class Discord extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint . '/oauth2/authorize?' . + $url = $this->endpoint.'/oauth2/authorize?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'redirect_uri' => $this->callback + 'redirect_uri' => $this->callback, ]); return $url; } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -67,7 +66,7 @@ class Discord extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth2/token', + $this->endpoint.'/oauth2/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', @@ -75,7 +74,7 @@ class Discord extends OAuth2 'redirect_uri' => $this->callback, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'scope' => \implode(' ', $this->getScopes()) + 'scope' => \implode(' ', $this->getScopes()), ]) ), true); } @@ -84,15 +83,14 @@ class Discord extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth2/token', + $this->endpoint.'/oauth2/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -110,8 +108,7 @@ class Discord extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -122,8 +119,7 @@ class Discord extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -138,8 +134,7 @@ class Discord extends OAuth2 * * @link https://discord.com/developers/docs/resources/user * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -154,8 +149,7 @@ class Discord extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -166,8 +160,7 @@ class Discord extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array @@ -175,8 +168,8 @@ class Discord extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - $this->endpoint . '/users/@me', - ['Authorization: Bearer ' . \urlencode($accessToken)] + $this->endpoint.'/users/@me', + ['Authorization: Bearer '.\urlencode($accessToken)] ); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Disqus.php b/src/Appwrite/Auth/OAuth2/Disqus.php index 58b7f48914..eb657298cd 100644 --- a/src/Appwrite/Auth/OAuth2/Disqus.php +++ b/src/Appwrite/Auth/OAuth2/Disqus.php @@ -45,21 +45,20 @@ class Disqus extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint . 'oauth/2.0/authorize/?' . + $url = $this->endpoint.'oauth/2.0/authorize/?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'state' => \json_encode($this->state), 'redirect_uri' => $this->callback, - 'scope' => \implode(',', $this->getScopes()) + 'scope' => \implode(',', $this->getScopes()), ]); return $url; } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -67,7 +66,7 @@ class Disqus extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'oauth/2.0/access_token/', + $this->endpoint.'oauth/2.0/access_token/', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', @@ -79,19 +78,19 @@ class Disqus extends OAuth2 ]) ), true); } + return $this->tokens; } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'oauth/2.0/access_token/?', + $this->endpoint.'oauth/2.0/access_token/?', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -104,12 +103,12 @@ class Disqus extends OAuth2 if (empty($this->tokens['refresh_token'])) { $this->tokens['refresh_token'] = $refreshToken; } + return $this->tokens; } /** - * @param string $token - * + * @param string $token * @return string */ public function getUserID(string $accessToken): string @@ -122,8 +121,7 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -136,13 +134,11 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { - // Look out for the change in their enpoint. // It's in Beta so they may provide a parameter in the future. // https://disqus.com/api/docs/users/details/ @@ -151,8 +147,7 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -165,8 +160,7 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array @@ -174,10 +168,10 @@ class Disqus extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - $this->endpoint . '3.0/users/details.json?' . \http_build_query([ + $this->endpoint.'3.0/users/details.json?'.\http_build_query([ 'access_token' => $accessToken, 'api_key' => $this->appID, - 'api_secret' => $this->appSecret + 'api_secret' => $this->appSecret, ]), ); $this->user = \json_decode($user, true)['response']; diff --git a/src/Appwrite/Auth/OAuth2/Dropbox.php b/src/Appwrite/Auth/OAuth2/Dropbox.php index ff30b87d8a..156f93e0ee 100644 --- a/src/Appwrite/Auth/OAuth2/Dropbox.php +++ b/src/Appwrite/Auth/OAuth2/Dropbox.php @@ -38,17 +38,16 @@ class Dropbox extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.dropbox.com/oauth2/authorize?' . \http_build_query([ + return 'https://www.dropbox.com/oauth2/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -64,7 +63,7 @@ class Dropbox extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -73,8 +72,7 @@ class Dropbox extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -88,7 +86,7 @@ class Dropbox extends OAuth2 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -100,8 +98,7 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -112,8 +109,7 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -128,8 +124,7 @@ class Dropbox extends OAuth2 * * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -144,8 +139,7 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -156,14 +150,13 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; $user = $this->request('POST', 'https://api.dropboxapi.com/2/users/get_current_account', $headers); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Etsy.php b/src/Appwrite/Auth/OAuth2/Etsy.php index 7ff16fcb78..7316cdc1d5 100644 --- a/src/Appwrite/Auth/OAuth2/Etsy.php +++ b/src/Appwrite/Auth/OAuth2/Etsy.php @@ -30,8 +30,8 @@ class Etsy extends OAuth2 * @var array */ protected array $scopes = [ - "email_r", - "profile_r", + 'email_r', + 'profile_r', ]; /** @@ -64,7 +64,7 @@ class Etsy extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.etsy.com/oauth/connect/oauth/authorize?' . \http_build_query([ + return 'https://www.etsy.com/oauth/connect/oauth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', @@ -76,8 +76,7 @@ class Etsy extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -87,7 +86,7 @@ class Etsy extends OAuth2 $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', $headers, \http_build_query([ 'grant_type' => 'authorization_code', @@ -103,8 +102,7 @@ class Etsy extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -113,7 +111,7 @@ class Etsy extends OAuth2 $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', $headers, \http_build_query([ 'grant_type' => 'refresh_token', @@ -131,7 +129,6 @@ class Etsy extends OAuth2 /** * @param $accessToken - * * @return string */ public function getUserID(string $accessToken): string @@ -143,7 +140,6 @@ class Etsy extends OAuth2 /** * @param $accessToken - * * @return string */ public function getUserEmail(string $accessToken): string @@ -156,20 +152,18 @@ class Etsy extends OAuth2 * * OAuth is only allowed if account has been verified through Etsy, itself. * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** * @param $accessToken - * * @return string */ public function getUserName(string $accessToken): string @@ -178,21 +172,20 @@ class Etsy extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { - if (!empty($this->user)) { + if (! empty($this->user)) { return $this->user; } - $headers = ['Authorization: Bearer ' . $accessToken]; + $headers = ['Authorization: Bearer '.$accessToken]; $this->user = \json_decode($this->request( 'GET', - 'https://api.etsy.com/v3/application/users/' . $this->getUserID($accessToken), + 'https://api.etsy.com/v3/application/users/'.$this->getUserID($accessToken), ), true); return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Exception.php b/src/Appwrite/Auth/OAuth2/Exception.php index 3d5b79d3b0..eddab9d400 100644 --- a/src/Appwrite/Auth/OAuth2/Exception.php +++ b/src/Appwrite/Auth/OAuth2/Exception.php @@ -7,7 +7,9 @@ use Appwrite\Extend\Exception as AppwriteException; class Exception extends AppwriteException { protected string $response = ''; + protected string $error = ''; + protected string $errorDescription = ''; public function __construct(string $response = '', int $code = 0, \Throwable $previous = null) @@ -19,11 +21,11 @@ class Exception extends AppwriteException if (\is_array($decoded['error'])) { $this->error = $decoded['error']['status']; $this->errorDescription = $decoded['error']['message']; - $this->message = $this->error . ': ' . $this->errorDescription; + $this->message = $this->error.': '.$this->errorDescription; } else { $this->error = $decoded['error']; $this->errorDescription = $decoded['error_description']; - $this->message = $this->error . ': ' . $this->errorDescription; + $this->message = $this->error.': '.$this->errorDescription; } } $type = match ($code) { diff --git a/src/Appwrite/Auth/OAuth2/Facebook.php b/src/Appwrite/Auth/OAuth2/Facebook.php index 90fe8e7388..9b10f3be80 100644 --- a/src/Appwrite/Auth/OAuth2/Facebook.php +++ b/src/Appwrite/Auth/OAuth2/Facebook.php @@ -25,7 +25,7 @@ class Facebook extends OAuth2 * @var array */ protected array $scopes = [ - 'email' + 'email', ]; /** @@ -41,17 +41,16 @@ class Facebook extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.facebook.com/' . $this->version . '/dialog/oauth?' . \http_build_query([ + return 'https://www.facebook.com/'.$this->version.'/dialog/oauth?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -59,11 +58,11 @@ class Facebook extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'GET', - 'https://graph.facebook.com/' . $this->version . '/oauth/access_token?' . \http_build_query([ + 'https://graph.facebook.com/'.$this->version.'/oauth/access_token?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, - 'code' => $code + 'code' => $code, ]) ), true); } @@ -72,20 +71,19 @@ class Facebook extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'GET', - 'https://graph.facebook.com/' . $this->version . '/oauth/access_token?' . \http_build_query([ + 'https://graph.facebook.com/'.$this->version.'/oauth/access_token?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -97,8 +95,7 @@ class Facebook extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -109,8 +106,7 @@ class Facebook extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -125,20 +121,18 @@ class Facebook extends OAuth2 * * If present, the email is verified. This was verfied through a manual Facebook sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -149,14 +143,13 @@ class Facebook extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://graph.facebook.com/' . $this->version . '/me?fields=email,name&access_token=' . \urlencode($accessToken)); + $user = $this->request('GET', 'https://graph.facebook.com/'.$this->version.'/me?fields=email,name&access_token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Firebase.php b/src/Appwrite/Auth/OAuth2/Firebase.php index 0a813881be..96638e83a3 100644 --- a/src/Appwrite/Auth/OAuth2/Firebase.php +++ b/src/Appwrite/Auth/OAuth2/Firebase.php @@ -24,7 +24,7 @@ class Firebase extends OAuth2 'https://www.googleapis.com/auth/datastore', 'https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/identitytoolkit', - 'https://www.googleapis.com/auth/userinfo.profile' + 'https://www.googleapis.com/auth/userinfo.profile', ]; /** @@ -40,7 +40,7 @@ class Firebase extends OAuth2 */ public function getLoginURL(): string { - return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([ + return 'https://accounts.google.com/o/oauth2/v2/auth?'.\http_build_query([ 'access_type' => 'offline', 'client_id' => $this->appID, 'redirect_uri' => $this->callback, @@ -52,8 +52,7 @@ class Firebase extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -68,19 +67,18 @@ class Firebase extends OAuth2 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'code' => $code, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ); - $this->tokens = \json_decode($response, true); + $this->tokens = \json_decode($response, true); } return $this->tokens; } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -93,7 +91,7 @@ class Firebase extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken + 'refresh_token' => $refreshToken, ]) ); @@ -108,10 +106,8 @@ class Firebase extends OAuth2 return $this->tokens; } - /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -122,8 +118,7 @@ class Firebase extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -133,14 +128,12 @@ class Firebase extends OAuth2 return $user['email'] ?? ''; } - /** * Check if the OAuth email is verified * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -155,8 +148,7 @@ class Firebase extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -167,8 +159,7 @@ class Firebase extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) @@ -176,7 +167,7 @@ class Firebase extends OAuth2 if (empty($this->user)) { $response = $this->request( 'GET', - 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' . \urlencode($accessToken), + 'https://www.googleapis.com/oauth2/v1/userinfo?access_token='.\urlencode($accessToken), [], ); @@ -188,7 +179,7 @@ class Firebase extends OAuth2 public function getProjects(string $accessToken): array { - $projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer ' . \urlencode($accessToken)]); + $projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer '.\urlencode($accessToken)]); $projects = \json_decode($projects, true); @@ -201,9 +192,9 @@ class Firebase extends OAuth2 public function assignIAMRoles(string $accessToken, string $email, string $projectId) { // Get IAM Roles - $iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':getIamPolicy', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' + $iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/'.$projectId.':getIamPolicy', [ + 'Authorization: Bearer '.\urlencode($accessToken), + 'Content-Type: application/json', ]); $iamRoles = \json_decode($iamRoles, true); @@ -211,23 +202,23 @@ class Firebase extends OAuth2 $iamRoles['bindings'][] = [ 'role' => 'roles/identitytoolkit.admin', 'members' => [ - 'serviceAccount:' . $email - ] + 'serviceAccount:'.$email, + ], ]; $iamRoles['bindings'][] = [ 'role' => 'roles/firebase.admin', 'members' => [ - 'serviceAccount:' . $email - ] + 'serviceAccount:'.$email, + ], ]; // Set IAM Roles - $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':setIamPolicy', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' + $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/'.$projectId.':setIamPolicy', [ + 'Authorization: Bearer '.\urlencode($accessToken), + 'Content-Type: application/json', ], json_encode([ - 'policy' => $iamRoles + 'policy' => $iamRoles, ])); } @@ -236,16 +227,16 @@ class Firebase extends OAuth2 // Create Service Account $response = $this->request( 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts', + 'https://iam.googleapis.com/v1/projects/'.$projectId.'/serviceAccounts', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' + 'Authorization: Bearer '.\urlencode($accessToken), + 'Content-Type: application/json', ], json_encode([ 'accountId' => 'appwrite-migrations', 'serviceAccount' => [ - 'displayName' => 'Appwrite Migrations' - ] + 'displayName' => 'Appwrite Migrations', + ], ]) ); @@ -256,10 +247,10 @@ class Firebase extends OAuth2 // Create Service Account Key $responseKey = $this->request( 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $response['email'] . '/keys', + 'https://iam.googleapis.com/v1/projects/'.$projectId.'/serviceAccounts/'.$response['email'].'/keys', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' + 'Authorization: Bearer '.\urlencode($accessToken), + 'Content-Type: application/json', ] ); diff --git a/src/Appwrite/Auth/OAuth2/Github.php b/src/Appwrite/Auth/OAuth2/Github.php index 8b9208fc06..ab67e17aa0 100644 --- a/src/Appwrite/Auth/OAuth2/Github.php +++ b/src/Appwrite/Auth/OAuth2/Github.php @@ -36,17 +36,16 @@ class Github extends OAuth2 */ public function getLoginURL(): string { - return 'https://github.com/login/oauth/authorize?' . \http_build_query([ + return 'https://github.com/login/oauth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -60,7 +59,7 @@ class Github extends OAuth2 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, - 'code' => $code + 'code' => $code, ]) ); @@ -73,8 +72,7 @@ class Github extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -87,7 +85,7 @@ class Github extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken + 'refresh_token' => $refreshToken, ]) ); @@ -103,8 +101,7 @@ class Github extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -115,8 +112,7 @@ class Github extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -131,8 +127,7 @@ class Github extends OAuth2 * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -147,8 +142,7 @@ class Github extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -159,8 +153,7 @@ class Github extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserSlug(string $accessToken): string @@ -171,16 +164,15 @@ class Github extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) { if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', 'https://api.github.com/user', ['Authorization: token ' . \urlencode($accessToken)]), true); + $this->user = \json_decode($this->request('GET', 'https://api.github.com/user', ['Authorization: token '.\urlencode($accessToken)]), true); - $emails = $this->request('GET', 'https://api.github.com/user/emails', ['Authorization: token ' . \urlencode($accessToken)]); + $emails = $this->request('GET', 'https://api.github.com/user/emails', ['Authorization: token '.\urlencode($accessToken)]); $emails = \json_decode($emails, true); @@ -197,10 +189,10 @@ class Github extends OAuth2 } } - if (!empty($primaryEmail)) { + if (! empty($primaryEmail)) { $this->user['email'] = $primaryEmail['email']; $this->user['verified'] = $primaryEmail['verified']; - } elseif (!empty($verifiedEmail)) { + } elseif (! empty($verifiedEmail)) { $this->user['email'] = $verifiedEmail['email']; $this->user['verified'] = $verifiedEmail['verified']; } diff --git a/src/Appwrite/Auth/OAuth2/Gitlab.php b/src/Appwrite/Auth/OAuth2/Gitlab.php index 7d98bf1921..f96348c98b 100644 --- a/src/Appwrite/Auth/OAuth2/Gitlab.php +++ b/src/Appwrite/Auth/OAuth2/Gitlab.php @@ -23,7 +23,7 @@ class Gitlab extends OAuth2 * @var array */ protected array $scopes = [ - 'read_user' + 'read_user', ]; /** @@ -39,18 +39,17 @@ class Gitlab extends OAuth2 */ public function getLoginURL(): string { - return $this->getEndpoint() . '/oauth/authorize?' . \http_build_query([ + return $this->getEndpoint().'/oauth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -58,12 +57,12 @@ class Gitlab extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->getEndpoint() . '/oauth/token?' . \http_build_query([ + $this->getEndpoint().'/oauth/token?'.\http_build_query([ 'code' => $code, 'client_id' => $this->appID, 'client_secret' => $this->getAppSecret()['clientSecret'], 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -72,19 +71,18 @@ class Gitlab extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->getEndpoint() . '/oauth/token?' . \http_build_query([ + $this->getEndpoint().'/oauth/token?'.\http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getAppSecret()['clientSecret'], - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -96,8 +94,7 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -112,8 +109,7 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -128,8 +124,7 @@ class Gitlab extends OAuth2 * * @link https://docs.gitlab.com/ee/api/users.html#list-current-user-for-normal-users * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -144,8 +139,7 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -156,14 +150,13 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', $this->getEndpoint() . '/api/v4/user?access_token=' . \urlencode($accessToken)); + $user = $this->request('GET', $this->getEndpoint().'/api/v4/user?access_token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); } @@ -182,10 +175,10 @@ class Gitlab extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } + return $secret; } - /** * Extracts the Tenant Id from the JSON stored in appSecret. Defaults to 'common' as a fallback * @@ -196,6 +189,7 @@ class Gitlab extends OAuth2 $defaultEndpoint = 'https://gitlab.com'; $secret = $this->getAppSecret(); $endpoint = $secret['endpoint'] ?? $defaultEndpoint; + return empty($endpoint) ? $defaultEndpoint : $endpoint; } } diff --git a/src/Appwrite/Auth/OAuth2/Google.php b/src/Appwrite/Auth/OAuth2/Google.php index c6f621b814..c56f1660c4 100644 --- a/src/Appwrite/Auth/OAuth2/Google.php +++ b/src/Appwrite/Auth/OAuth2/Google.php @@ -22,7 +22,7 @@ class Google extends OAuth2 protected array $scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', - 'openid' + 'openid', ]; /** @@ -48,18 +48,17 @@ class Google extends OAuth2 */ public function getLoginURL(): string { - return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([ + return 'https://accounts.google.com/o/oauth2/v2/auth?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -67,13 +66,13 @@ class Google extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - 'https://oauth2.googleapis.com/token?' . \http_build_query([ + 'https://oauth2.googleapis.com/token?'.\http_build_query([ 'code' => $code, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'redirect_uri' => $this->callback, 'scope' => null, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -82,19 +81,18 @@ class Google extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - 'https://oauth2.googleapis.com/token?' . \http_build_query([ + 'https://oauth2.googleapis.com/token?'.\http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -106,8 +104,7 @@ class Google extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -118,8 +115,7 @@ class Google extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -134,8 +130,7 @@ class Google extends OAuth2 * * @link https://www.oauth.com/oauth2-servers/signing-in-with-google/verifying-the-user-info/ * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -150,8 +145,7 @@ class Google extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -162,14 +156,13 @@ class Google extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://www.googleapis.com/oauth2/v3/userinfo?access_token=' . \urlencode($accessToken)); + $user = $this->request('GET', 'https://www.googleapis.com/oauth2/v3/userinfo?access_token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Linkedin.php b/src/Appwrite/Auth/OAuth2/Linkedin.php index 340cab2df0..c4e899b5ca 100644 --- a/src/Appwrite/Auth/OAuth2/Linkedin.php +++ b/src/Appwrite/Auth/OAuth2/Linkedin.php @@ -50,7 +50,7 @@ class Linkedin extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.linkedin.com/oauth/v2/authorization?' . \http_build_query([ + return 'https://www.linkedin.com/oauth/v2/authorization?'.\http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'redirect_uri' => $this->callback, @@ -60,8 +60,7 @@ class Linkedin extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -80,12 +79,12 @@ class Linkedin extends OAuth2 ]) ), true); } + return $this->tokens; } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -106,12 +105,12 @@ class Linkedin extends OAuth2 if (empty($this->tokens['refresh_token'])) { $this->tokens['refresh_token'] = $refreshToken; } + return $this->tokens; } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -122,13 +121,12 @@ class Linkedin extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string { - $email = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', ['Authorization: Bearer ' . \urlencode($accessToken)]), true); + $email = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', ['Authorization: Bearer '.\urlencode($accessToken)]), true); return $email['elements'][0]['handle~']['emailAddress'] ?? ''; } @@ -138,20 +136,18 @@ class Linkedin extends OAuth2 * * If present, the email is verified. This was verfied through a manual Linkedin sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -164,21 +160,20 @@ class Linkedin extends OAuth2 } if (isset($user['localizedLastName'])) { - $name = (empty($name)) ? $user['localizedLastName'] : $name . ' ' . $user['localizedLastName']; + $name = (empty($name)) ? $user['localizedLastName'] : $name.' '.$user['localizedLastName']; } return $name; } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) { if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/me', ['Authorization: Bearer ' . \urlencode($accessToken)]), true); + $this->user = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/me', ['Authorization: Bearer '.\urlencode($accessToken)]), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Microsoft.php b/src/Appwrite/Auth/OAuth2/Microsoft.php index bc05843b37..89b77c1925 100644 --- a/src/Appwrite/Auth/OAuth2/Microsoft.php +++ b/src/Appwrite/Auth/OAuth2/Microsoft.php @@ -25,7 +25,7 @@ class Microsoft extends OAuth2 */ protected array $scopes = [ 'offline_access', - 'user.read' + 'user.read', ]; /** @@ -41,19 +41,18 @@ class Microsoft extends OAuth2 */ public function getLoginURL(): string { - return 'https://login.microsoftonline.com/' . $this->getTenantID() . '/oauth2/v2.0/authorize?' . \http_build_query([ + return 'https://login.microsoftonline.com/'.$this->getTenantID().'/oauth2/v2.0/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), 'response_type' => 'code', - 'response_mode' => 'query' + 'response_mode' => 'query', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -62,7 +61,7 @@ class Microsoft extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://login.microsoftonline.com/' . $this->getTenantID() . '/oauth2/v2.0/token', + 'https://login.microsoftonline.com/'.$this->getTenantID().'/oauth2/v2.0/token', $headers, \http_build_query([ 'code' => $code, @@ -70,7 +69,7 @@ class Microsoft extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -79,8 +78,7 @@ class Microsoft extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -88,13 +86,13 @@ class Microsoft extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://login.microsoftonline.com/' . $this->getTenantID() . '/oauth2/v2.0/token', + 'https://login.microsoftonline.com/'.$this->getTenantID().'/oauth2/v2.0/token', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -106,8 +104,7 @@ class Microsoft extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -118,8 +115,7 @@ class Microsoft extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -134,20 +130,18 @@ class Microsoft extends OAuth2 * * If present, the email is verified. This was verfied through a manual Microsoft sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -158,14 +152,13 @@ class Microsoft extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; $user = $this->request('GET', 'https://graph.microsoft.com/v1.0/me', $headers); $this->user = \json_decode($user, true); } @@ -185,6 +178,7 @@ class Microsoft extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } + return $secret; } diff --git a/src/Appwrite/Auth/OAuth2/Mock.php b/src/Appwrite/Auth/OAuth2/Mock.php index d2cb8c1c2a..b0b2e3b8d1 100644 --- a/src/Appwrite/Auth/OAuth2/Mock.php +++ b/src/Appwrite/Auth/OAuth2/Mock.php @@ -3,7 +3,6 @@ namespace Appwrite\Auth\OAuth2; use Appwrite\Auth\OAuth2; -use Utopia\Exception; class Mock extends OAuth2 { @@ -16,7 +15,7 @@ class Mock extends OAuth2 * @var array */ protected array $scopes = [ - 'email' + 'email', ]; /** @@ -42,17 +41,16 @@ class Mock extends OAuth2 */ public function getLoginURL(): string { - return 'http://localhost/' . $this->version . '/mock/tests/general/oauth2?' . \http_build_query([ + return 'http://localhost/'.$this->version.'/mock/tests/general/oauth2?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -60,12 +58,12 @@ class Mock extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'GET', - 'http://localhost/' . $this->version . '/mock/tests/general/oauth2/token?' . + 'http://localhost/'.$this->version.'/mock/tests/general/oauth2/token?'. \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, - 'code' => $code + 'code' => $code, ]) ), true); } @@ -74,20 +72,19 @@ class Mock extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'GET', - 'http://localhost/' . $this->version . '/mock/tests/general/oauth2/token?' . + 'http://localhost/'.$this->version.'/mock/tests/general/oauth2/token?'. \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -99,8 +96,7 @@ class Mock extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -111,8 +107,7 @@ class Mock extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -125,8 +120,7 @@ class Mock extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -135,8 +129,7 @@ class Mock extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -147,14 +140,13 @@ class Mock extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'http://localhost/' . $this->version . '/mock/tests/general/oauth2/user?token=' . \urlencode($accessToken)); + $user = $this->request('GET', 'http://localhost/'.$this->version.'/mock/tests/general/oauth2/user?token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Notion.php b/src/Appwrite/Auth/OAuth2/Notion.php index c2f1ee98e4..17c1dd7f18 100644 --- a/src/Appwrite/Auth/OAuth2/Notion.php +++ b/src/Appwrite/Auth/OAuth2/Notion.php @@ -44,32 +44,31 @@ class Notion extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . '/oauth/authorize?' . \http_build_query([ + return $this->endpoint.'/oauth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', 'state' => \json_encode($this->state), - 'owner' => 'user' + 'owner' => 'user', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { - $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; + $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', $headers, \http_build_query([ 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callback, - 'code' => $code + 'code' => $code, ]) ), true); } @@ -78,16 +77,15 @@ class Notion extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { - $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; + $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', $headers, \http_build_query([ 'grant_type' => 'refresh_token', @@ -103,8 +101,7 @@ class Notion extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -115,8 +112,7 @@ class Notion extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -131,20 +127,18 @@ class Notion extends OAuth2 * * If present, the email is verified. This was verfied through a manual Notion sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -155,19 +149,18 @@ class Notion extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { $headers = [ - 'Notion-Version: ' . $this->version, - 'Authorization: Bearer ' . \urlencode($accessToken) + 'Notion-Version: '.$this->version, + 'Authorization: Bearer '.\urlencode($accessToken), ]; if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', $this->endpoint . '/users/me', $headers), true); + $this->user = \json_decode($this->request('GET', $this->endpoint.'/users/me', $headers), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Oidc.php b/src/Appwrite/Auth/OAuth2/Oidc.php index de2eab65c8..dfdf9aeff0 100644 --- a/src/Appwrite/Auth/OAuth2/Oidc.php +++ b/src/Appwrite/Auth/OAuth2/Oidc.php @@ -43,7 +43,7 @@ class Oidc extends OAuth2 */ public function getLoginURL(): string { - return $this->getAuthorizationEndpoint() . '?' . \http_build_query([ + return $this->getAuthorizationEndpoint().'?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), @@ -53,8 +53,7 @@ class Oidc extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -71,17 +70,16 @@ class Oidc extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } + return $this->tokens; } - /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -95,7 +93,7 @@ class Oidc extends OAuth2 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -107,8 +105,7 @@ class Oidc extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -123,8 +120,7 @@ class Oidc extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -141,8 +137,7 @@ class Oidc extends OAuth2 /** * Check if the User email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -153,8 +148,7 @@ class Oidc extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -168,15 +162,14 @@ class Oidc extends OAuth2 return ''; } - /** - * @param string $accessToken - * + /** + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; $user = $this->request('GET', $this->getUserinfoEndpoint(), $headers); $this->user = \json_decode($user, true); } @@ -196,7 +189,7 @@ class Oidc extends OAuth2 return $secret['clientSecret'] ?? ''; } - /** + /** * Extracts the well known endpoint from the JSON stored in appSecret. * * @return string @@ -204,13 +197,14 @@ class Oidc extends OAuth2 protected function getWellKnownEndpoint(): string { $secret = $this->getAppSecret(); + return $secret['wellKnownEndpoint'] ?? ''; } /** - * Extracts the authorization endpoint from the JSON stored in appSecret. - * - * If one is not provided, it will be retrieved from the well-known configuration. + * Extracts the authorization endpoint from the JSON stored in appSecret. + * + * If one is not provided, it will be retrieved from the well-known configuration. * * @return string */ @@ -219,56 +213,59 @@ class Oidc extends OAuth2 $secret = $this->getAppSecret(); $endpoint = $secret['authorizationEndpoint'] ?? ''; - if (!empty($endpoint)) { + if (! empty($endpoint)) { return $endpoint; } $wellKnownConfiguration = $this->getWellKnownConfiguration(); + return $wellKnownConfiguration['authorization_endpoint'] ?? ''; } /** - * Extracts the token endpoint from the JSON stored in appSecret. - * - * If one is not provided, it will be retrieved from the well-known configuration. - * - * @return string - */ + * Extracts the token endpoint from the JSON stored in appSecret. + * + * If one is not provided, it will be retrieved from the well-known configuration. + * + * @return string + */ protected function getTokenEndpoint(): string { $secret = $this->getAppSecret(); $endpoint = $secret['tokenEndpoint'] ?? ''; - if (!empty($endpoint)) { + if (! empty($endpoint)) { return $endpoint; } $wellKnownConfiguration = $this->getWellKnownConfiguration(); + return $wellKnownConfiguration['token_endpoint'] ?? ''; } /** - * Extracts the userinfo endpoint from the JSON stored in appSecret. - * - * If one is not provided, it will be retrieved from the well-known configuration. - * - * @return string - */ + * Extracts the userinfo endpoint from the JSON stored in appSecret. + * + * If one is not provided, it will be retrieved from the well-known configuration. + * + * @return string + */ protected function getUserinfoEndpoint(): string { $secret = $this->getAppSecret(); $endpoint = $secret['userinfoEndpoint'] ?? ''; - if (!empty($endpoint)) { + if (! empty($endpoint)) { return $endpoint; } $wellKnownConfiguration = $this->getWellKnownConfiguration(); + return $wellKnownConfiguration['userinfo_endpoint'] ?? ''; } - /** - * Get the well-known configuration using the well known endpoint - */ + /** + * Get the well-known configuration using the well known endpoint + */ protected function getWellKnownConfiguration(): array { if (empty($this->wellKnownConfiguration)) { @@ -291,6 +288,7 @@ class Oidc extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } + return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Okta.php b/src/Appwrite/Auth/OAuth2/Okta.php index 610d9847f2..367c64e764 100644 --- a/src/Appwrite/Auth/OAuth2/Okta.php +++ b/src/Appwrite/Auth/OAuth2/Okta.php @@ -16,7 +16,7 @@ class Okta extends OAuth2 'openid', 'profile', 'email', - 'offline_access' + 'offline_access', ]; /** @@ -42,18 +42,17 @@ class Okta extends OAuth2 */ public function getLoginURL(): string { - return 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/authorize?' . \http_build_query([ + return 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'response_type' => 'code' + 'response_type' => 'code', ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -62,7 +61,7 @@ class Okta extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/token', + 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/token', $headers, \http_build_query([ 'code' => $code, @@ -70,7 +69,7 @@ class Okta extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -78,10 +77,8 @@ class Okta extends OAuth2 return $this->tokens; } - /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -89,13 +86,13 @@ class Okta extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/token', + 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/token', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -107,8 +104,7 @@ class Okta extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -119,8 +115,7 @@ class Okta extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -135,8 +130,7 @@ class Okta extends OAuth2 * * @link https://developer.okta.com/docs/reference/api/oidc/#userinfo * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -151,8 +145,7 @@ class Okta extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -163,15 +156,14 @@ class Okta extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; - $user = $this->request('GET', 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/userinfo', $headers); + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $user = $this->request('GET', 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/userinfo', $headers); $this->user = \json_decode($user, true); } @@ -226,6 +218,7 @@ class Okta extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } + return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Paypal.php b/src/Appwrite/Auth/OAuth2/Paypal.php index 5d5bd0a06f..e55ed05ac4 100644 --- a/src/Appwrite/Auth/OAuth2/Paypal.php +++ b/src/Appwrite/Auth/OAuth2/Paypal.php @@ -46,7 +46,7 @@ class Paypal extends OAuth2 protected array $scopes = [ 'openid', 'profile', - 'email' + 'email', ]; /** @@ -62,14 +62,14 @@ class Paypal extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint[$this->environment] . 'connect/?' . + $url = $this->endpoint[$this->environment].'connect/?'. \http_build_query([ 'flowEntry' => 'static', 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), // paypal is not accepting localhost string into return uri - 'redirect_uri' => \str_replace("localhost", "127.0.0.1", $this->callback), + 'redirect_uri' => \str_replace('localhost', '127.0.0.1', $this->callback), 'state' => \json_encode($this->state), ]); @@ -77,8 +77,7 @@ class Paypal extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -86,8 +85,8 @@ class Paypal extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->resourceEndpoint[$this->environment] . 'oauth2/token', - ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], + $this->resourceEndpoint[$this->environment].'oauth2/token', + ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], \http_build_query([ 'code' => $code, 'grant_type' => 'authorization_code', @@ -99,16 +98,15 @@ class Paypal extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->resourceEndpoint[$this->environment] . 'oauth2/token', - ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], + $this->resourceEndpoint[$this->environment].'oauth2/token', + ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], \http_build_query([ 'refresh_token' => $refreshToken, 'grant_type' => 'refresh_token', @@ -123,8 +121,7 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -135,8 +132,7 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -148,7 +144,7 @@ class Paypal extends OAuth2 return $email['primary'] === true; }); - if (!empty($email)) { + if (! empty($email)) { return $email[0]['value']; } } @@ -161,8 +157,7 @@ class Paypal extends OAuth2 * * @link https://developer.paypal.com/docs/api/identity/v1/#userinfo_get * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -177,8 +172,7 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -189,20 +183,19 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { $header = [ 'Content-Type: application/json', - 'Authorization: Bearer ' . \urlencode($accessToken), + 'Authorization: Bearer '.\urlencode($accessToken), ]; if (empty($this->user)) { $user = $this->request( 'GET', - $this->resourceEndpoint[$this->environment] . 'identity/oauth2/userinfo?schema=paypalv1.1', + $this->resourceEndpoint[$this->environment].'identity/oauth2/userinfo?schema=paypalv1.1', $header ); $this->user = \json_decode($user, true); diff --git a/src/Appwrite/Auth/OAuth2/PaypalSandbox.php b/src/Appwrite/Auth/OAuth2/PaypalSandbox.php index 0f56a09c21..e5ab612c0d 100644 --- a/src/Appwrite/Auth/OAuth2/PaypalSandbox.php +++ b/src/Appwrite/Auth/OAuth2/PaypalSandbox.php @@ -2,8 +2,6 @@ namespace Appwrite\Auth\OAuth2; -use Appwrite\Auth\OAuth2\Paypal; - class PaypalSandbox extends Paypal { protected string $environment = 'sandbox'; diff --git a/src/Appwrite/Auth/OAuth2/Podio.php b/src/Appwrite/Auth/OAuth2/Podio.php index e4194238d1..f3ba81968e 100644 --- a/src/Appwrite/Auth/OAuth2/Podio.php +++ b/src/Appwrite/Auth/OAuth2/Podio.php @@ -51,19 +51,18 @@ class Podio extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint . '/authorize?' . + $url = $this->endpoint.'/authorize?'. \http_build_query([ 'client_id' => $this->appID, 'state' => \json_encode($this->state), - 'redirect_uri' => $this->callback + 'redirect_uri' => $this->callback, ]); return $url; } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -71,14 +70,14 @@ class Podio extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->apiEndpoint . '/oauth/token', + $this->apiEndpoint.'/oauth/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, 'redirect_uri' => $this->callback, 'client_id' => $this->appID, - 'client_secret' => $this->appSecret + 'client_secret' => $this->appSecret, ]) ), true); } @@ -87,15 +86,14 @@ class Podio extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->apiEndpoint . '/oauth/token', + $this->apiEndpoint.'/oauth/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -113,8 +111,7 @@ class Podio extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -125,8 +122,7 @@ class Podio extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -139,8 +135,7 @@ class Podio extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -148,7 +143,7 @@ class Podio extends OAuth2 $user = $this->getUser($accessToken); $mails = $user['mails']; - $mainMailIndex = \array_search($user['mail'], \array_map(fn($m) => $m['mail'], $mails)); + $mainMailIndex = \array_search($user['mail'], \array_map(fn ($m) => $m['mail'], $mails)); $mainMain = $mails[$mainMailIndex]; if ($mainMain['verified'] ?? false) { @@ -159,8 +154,7 @@ class Podio extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -171,8 +165,7 @@ class Podio extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array @@ -180,14 +173,14 @@ class Podio extends OAuth2 if (empty($this->user)) { $user = \json_decode($this->request( 'GET', - $this->apiEndpoint . '/user', - ['Authorization: Bearer ' . \urlencode($accessToken)] + $this->apiEndpoint.'/user', + ['Authorization: Bearer '.\urlencode($accessToken)] ), true); $profile = \json_decode($this->request( 'GET', - $this->apiEndpoint . '/user/profile', - ['Authorization: Bearer ' . \urlencode($accessToken)] + $this->apiEndpoint.'/user/profile', + ['Authorization: Bearer '.\urlencode($accessToken)] ), true); $this->user = $user; diff --git a/src/Appwrite/Auth/OAuth2/Salesforce.php b/src/Appwrite/Auth/OAuth2/Salesforce.php index 564fc51139..5fede655df 100644 --- a/src/Appwrite/Auth/OAuth2/Salesforce.php +++ b/src/Appwrite/Auth/OAuth2/Salesforce.php @@ -25,7 +25,7 @@ class Salesforce extends OAuth2 * @var array */ protected array $scopes = [ - "openid" + 'openid', ]; /** @@ -37,8 +37,7 @@ class Salesforce extends OAuth2 } /** - * @param string $state - * + * @param string $state * @return array */ public function parseState(string $state) @@ -46,31 +45,29 @@ class Salesforce extends OAuth2 return \json_decode(\html_entity_decode($state), true); } - /** * @return string */ public function getLoginURL(): string { - return 'https://login.salesforce.com/services/oauth2/authorize?' . \http_build_query([ + return 'https://login.salesforce.com/services/oauth2/authorize?'.\http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { $headers = [ - 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), + 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -80,7 +77,7 @@ class Salesforce extends OAuth2 \http_build_query([ 'code' => $code, 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -89,14 +86,13 @@ class Salesforce extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $headers = [ - 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), + 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -105,7 +101,7 @@ class Salesforce extends OAuth2 $headers, \http_build_query([ 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -117,8 +113,7 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -129,8 +124,7 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -145,8 +139,7 @@ class Salesforce extends OAuth2 * * @link https://help.salesforce.com/s/articleView?id=sf.remoteaccess_using_userinfo_endpoint.htm&type=5 * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -161,8 +154,7 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -173,16 +165,16 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://login.salesforce.com/services/oauth2/userinfo?access_token=' . \urlencode($accessToken)); + $user = $this->request('GET', 'https://login.salesforce.com/services/oauth2/userinfo?access_token='.\urlencode($accessToken)); $this->user = \json_decode($user, true); } + return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Slack.php b/src/Appwrite/Auth/OAuth2/Slack.php index 8898f4d1f7..ee6d43c0cc 100644 --- a/src/Appwrite/Auth/OAuth2/Slack.php +++ b/src/Appwrite/Auth/OAuth2/Slack.php @@ -23,7 +23,7 @@ class Slack extends OAuth2 'identity.avatar', 'identity.basic', 'identity.email', - 'identity.team' + 'identity.team', ]; /** @@ -40,17 +40,16 @@ class Slack extends OAuth2 public function getLoginURL(): string { // https://api.slack.com/docs/oauth#step_1_-_sending_users_to_authorize_and_or_install - return 'https://slack.com/oauth/authorize?' . \http_build_query([ + return 'https://slack.com/oauth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -59,11 +58,11 @@ class Slack extends OAuth2 // https://api.slack.com/docs/oauth#step_3_-_exchanging_a_verification_code_for_an_access_token $this->tokens = \json_decode($this->request( 'GET', - 'https://slack.com/api/oauth.access?' . \http_build_query([ + 'https://slack.com/api/oauth.access?'.\http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'code' => $code, - 'redirect_uri' => $this->callback + 'redirect_uri' => $this->callback, ]) ), true); } @@ -72,19 +71,18 @@ class Slack extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'GET', - 'https://slack.com/api/oauth.access?' . \http_build_query([ + 'https://slack.com/api/oauth.access?'.\http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -96,8 +94,7 @@ class Slack extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -108,8 +105,7 @@ class Slack extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -126,20 +122,18 @@ class Slack extends OAuth2 * * @link https://slack.com/help/articles/207262907-Change-your-email-address * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -152,8 +146,7 @@ class Slack extends OAuth2 /** * @link https://api.slack.com/methods/users.identity * - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array @@ -161,7 +154,7 @@ class Slack extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - 'https://slack.com/api/users.identity?token=' . \urlencode($accessToken) + 'https://slack.com/api/users.identity?token='.\urlencode($accessToken) ); $this->user = \json_decode($user, true); diff --git a/src/Appwrite/Auth/OAuth2/Spotify.php b/src/Appwrite/Auth/OAuth2/Spotify.php index d8e23cf0f0..a8d5c531ab 100644 --- a/src/Appwrite/Auth/OAuth2/Spotify.php +++ b/src/Appwrite/Auth/OAuth2/Spotify.php @@ -49,33 +49,32 @@ class Spotify extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . 'authorize?' . + return $this->endpoint.'authorize?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { - $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; + $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'api/token', + $this->endpoint.'api/token', $headers, \http_build_query([ - "code" => $code, - "grant_type" => "authorization_code", - "redirect_uri" => $this->callback + 'code' => $code, + 'grant_type' => 'authorization_code', + 'redirect_uri' => $this->callback, ]) ), true); } @@ -84,20 +83,19 @@ class Spotify extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { - $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; + $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'api/token', + $this->endpoint.'api/token', $headers, \http_build_query([ - "refresh_token" => $refreshToken, - "grant_type" => "refresh_token", + 'refresh_token' => $refreshToken, + 'grant_type' => 'refresh_token', ]) ), true); @@ -109,8 +107,7 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -121,8 +118,7 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -139,8 +135,7 @@ class Spotify extends OAuth2 * * @link https://developer.spotify.com/documentation/web-api/reference/#/operations/get-current-users-profile * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -149,8 +144,7 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -161,8 +155,7 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) @@ -170,8 +163,8 @@ class Spotify extends OAuth2 if (empty($this->user)) { $this->user = \json_decode($this->request( 'GET', - $this->resourceEndpoint . 'me', - ['Authorization: Bearer ' . \urlencode($accessToken)] + $this->resourceEndpoint.'me', + ['Authorization: Bearer '.\urlencode($accessToken)] ), true); } diff --git a/src/Appwrite/Auth/OAuth2/Stripe.php b/src/Appwrite/Auth/OAuth2/Stripe.php index 5a959dbfcb..42260cad1e 100644 --- a/src/Appwrite/Auth/OAuth2/Stripe.php +++ b/src/Appwrite/Auth/OAuth2/Stripe.php @@ -3,7 +3,6 @@ namespace Appwrite\Auth\OAuth2; use Appwrite\Auth\OAuth2; -use Utopia\Exception; class Stripe extends OAuth2 { @@ -50,18 +49,17 @@ class Stripe extends OAuth2 */ public function getLoginURL(): string { - return 'https://connect.stripe.com/oauth/authorize?' . \http_build_query([ + return 'https://connect.stripe.com/oauth/authorize?'.\http_build_query([ 'response_type' => 'code', // The only option at the moment is "code." 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -73,7 +71,7 @@ class Stripe extends OAuth2 [], \http_build_query([ 'grant_type' => $this->grantType['authorize'], - 'code' => $code + 'code' => $code, ]) ), true); @@ -84,8 +82,7 @@ class Stripe extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -105,12 +102,12 @@ class Stripe extends OAuth2 } $this->stripeAccountId = $this->tokens['stripe_user_id']; + return $this->tokens; } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -121,8 +118,7 @@ class Stripe extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -141,20 +137,18 @@ class Stripe extends OAuth2 * * If present, the email is verified. This was verfied through a manual Stripe sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -165,18 +159,17 @@ class Stripe extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) { - if (empty($this->user) && !empty($this->stripeAccountId)) { + if (empty($this->user) && ! empty($this->stripeAccountId)) { $this->user = \json_decode( $this->request( 'GET', - 'https://api.stripe.com/v1/accounts/' . $this->stripeAccountId, - ['Authorization: Bearer ' . \urlencode($accessToken)] + 'https://api.stripe.com/v1/accounts/'.$this->stripeAccountId, + ['Authorization: Bearer '.\urlencode($accessToken)] ), true ); diff --git a/src/Appwrite/Auth/OAuth2/Tradeshift.php b/src/Appwrite/Auth/OAuth2/Tradeshift.php index 8d0bfa8784..350c152e4c 100644 --- a/src/Appwrite/Auth/OAuth2/Tradeshift.php +++ b/src/Appwrite/Auth/OAuth2/Tradeshift.php @@ -10,6 +10,7 @@ use Appwrite\Auth\OAuth2; class Tradeshift extends OAuth2 { public const TRADESHIFT_SANDBOX_API_DOMAIN = 'api-sandbox.tradeshift.com'; + public const TRADESHIFT_API_DOMAIN = 'api.tradeshift.com'; private array $apiDomain = [ @@ -18,13 +19,13 @@ class Tradeshift extends OAuth2 ]; private array $endpoint = [ - 'sandbox' => 'https://' . self::TRADESHIFT_SANDBOX_API_DOMAIN . '/tradeshift/', - 'live' => 'https://' . self::TRADESHIFT_API_DOMAIN . '/tradeshift/', + 'sandbox' => 'https://'.self::TRADESHIFT_SANDBOX_API_DOMAIN.'/tradeshift/', + 'live' => 'https://'.self::TRADESHIFT_API_DOMAIN.'/tradeshift/', ]; private array $resourceEndpoint = [ - 'sandbox' => 'https://' . self::TRADESHIFT_SANDBOX_API_DOMAIN . '/tradeshift/rest/external/', - 'live' => 'https://' . self::TRADESHIFT_API_DOMAIN . '/tradeshift/rest/external/', + 'sandbox' => 'https://'.self::TRADESHIFT_SANDBOX_API_DOMAIN.'/tradeshift/rest/external/', + 'live' => 'https://'.self::TRADESHIFT_API_DOMAIN.'/tradeshift/rest/external/', ]; protected string $environment = 'live'; @@ -64,18 +65,17 @@ class Tradeshift extends OAuth2 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), - 'redirect_uri' => \str_replace("localhost", "127.0.0.1", $this->callback), + 'redirect_uri' => \str_replace('localhost', '127.0.0.1', $this->callback), 'state' => \json_encode($this->state), ]); - $url = $this->endpoint[$this->environment] . 'auth/login?' . $httpQuery; + $url = $this->endpoint[$this->environment].'auth/login?'.$httpQuery; return $url; } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -83,8 +83,8 @@ class Tradeshift extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint[$this->environment] . 'auth/token', - ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], + $this->endpoint[$this->environment].'auth/token', + ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], \http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, @@ -96,16 +96,15 @@ class Tradeshift extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint[$this->environment] . 'auth/token', - ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], + $this->endpoint[$this->environment].'auth/token', + ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], \http_build_query([ 'grant_type' => 'refresh_token', 'refresh_token' => $refreshToken, @@ -120,8 +119,7 @@ class Tradeshift extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -132,8 +130,7 @@ class Tradeshift extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -148,20 +145,18 @@ class Tradeshift extends OAuth2 * * If present, the email is verified. This was verfied through a manual Tradeshift sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUser($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -171,12 +166,11 @@ class Tradeshift extends OAuth2 $firstName = $user['FirstName'] ?? ''; $lastName = $user['LastName'] ?? ''; - return $firstName . ' ' . $lastName; + return $firstName.' '.$lastName; } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array @@ -184,14 +178,14 @@ class Tradeshift extends OAuth2 $header = [ 'Content-Type: application/json', 'Accept: application/json', - 'Host: ' . urlencode($this->apiDomain[$this->environment]), - 'Authorization: Bearer ' . $accessToken, + 'Host: '.urlencode($this->apiDomain[$this->environment]), + 'Authorization: Bearer '.$accessToken, ]; if (empty($this->user)) { $response = $this->request( 'GET', - $this->resourceEndpoint[$this->environment] . 'account/info/user', + $this->resourceEndpoint[$this->environment].'account/info/user', $header ); $this->user = \json_decode($response, true); diff --git a/src/Appwrite/Auth/OAuth2/TradeshiftBox.php b/src/Appwrite/Auth/OAuth2/TradeshiftBox.php index 27a4c0a456..d960acf2d3 100644 --- a/src/Appwrite/Auth/OAuth2/TradeshiftBox.php +++ b/src/Appwrite/Auth/OAuth2/TradeshiftBox.php @@ -2,8 +2,6 @@ namespace Appwrite\Auth\OAuth2; -use Appwrite\Auth\OAuth2\Tradeshift; - class TradeshiftBox extends Tradeshift { protected string $environment = 'sandbox'; diff --git a/src/Appwrite/Auth/OAuth2/Twitch.php b/src/Appwrite/Auth/OAuth2/Twitch.php index ed73054c31..dad2efe800 100644 --- a/src/Appwrite/Auth/OAuth2/Twitch.php +++ b/src/Appwrite/Auth/OAuth2/Twitch.php @@ -49,20 +49,19 @@ class Twitch extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . 'authorize?' . + return $this->endpoint.'authorize?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, 'force_verify' => true, - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -70,12 +69,12 @@ class Twitch extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'token?' . \http_build_query([ - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "code" => $code, - "grant_type" => "authorization_code", - "redirect_uri" => $this->callback + $this->endpoint.'token?'.\http_build_query([ + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'code' => $code, + 'grant_type' => 'authorization_code', + 'redirect_uri' => $this->callback, ]) ), true); } @@ -84,19 +83,18 @@ class Twitch extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'token?' . \http_build_query([ - "client_id" => $this->appID, - "client_secret" => $this->appSecret, - "refresh_token" => $refreshToken, - "grant_type" => "refresh_token", + $this->endpoint.'token?'.\http_build_query([ + 'client_id' => $this->appID, + 'client_secret' => $this->appSecret, + 'refresh_token' => $refreshToken, + 'grant_type' => 'refresh_token', ]) ), true); @@ -108,8 +106,7 @@ class Twitch extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -120,8 +117,7 @@ class Twitch extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -138,20 +134,18 @@ class Twitch extends OAuth2 * * @link https://dev.twitch.tv/docs/api/reference#get-users * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -162,8 +156,7 @@ class Twitch extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) @@ -173,8 +166,8 @@ class Twitch extends OAuth2 'GET', $this->resourceEndpoint, [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Client-Id: ' . \urlencode($this->appID) + 'Authorization: Bearer '.\urlencode($accessToken), + 'Client-Id: '.\urlencode($this->appID), ] ), true); diff --git a/src/Appwrite/Auth/OAuth2/WordPress.php b/src/Appwrite/Auth/OAuth2/WordPress.php index 1bd55916fc..084b890a5d 100644 --- a/src/Appwrite/Auth/OAuth2/WordPress.php +++ b/src/Appwrite/Auth/OAuth2/WordPress.php @@ -39,18 +39,17 @@ class WordPress extends OAuth2 */ public function getLoginURL(): string { - return 'https://public-api.wordpress.com/oauth2/authorize?' . \http_build_query([ + return 'https://public-api.wordpress.com/oauth2/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', 'scope' => $this->getScopes(), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -65,7 +64,7 @@ class WordPress extends OAuth2 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'grant_type' => 'authorization_code', - 'code' => $code + 'code' => $code, ]) ), true); } @@ -74,8 +73,7 @@ class WordPress extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -88,7 +86,7 @@ class WordPress extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken + 'refresh_token' => $refreshToken, ]) ), true); @@ -100,8 +98,7 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -112,8 +109,7 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -132,8 +128,7 @@ class WordPress extends OAuth2 * * @link https://developer.wordpress.com/docs/api/1.1/get/me/ * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -148,8 +143,7 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -160,14 +154,13 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) { if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', 'https://public-api.wordpress.com/rest/v1/me', ['Authorization: Bearer ' . $accessToken]), true); + $this->user = \json_decode($this->request('GET', 'https://public-api.wordpress.com/rest/v1/me', ['Authorization: Bearer '.$accessToken]), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Yahoo.php b/src/Appwrite/Auth/OAuth2/Yahoo.php index c70a2fb6c9..82496d666c 100644 --- a/src/Appwrite/Auth/OAuth2/Yahoo.php +++ b/src/Appwrite/Auth/OAuth2/Yahoo.php @@ -45,10 +45,8 @@ class Yahoo extends OAuth2 return 'yahoo'; } - /** * @param $state - * * @return array */ public function parseState(string $state) @@ -61,37 +59,36 @@ class Yahoo extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . 'request_auth?' . + return $this->endpoint.'request_auth?'. \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { $headers = [ - 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), + 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'get_token', + $this->endpoint.'get_token', $headers, \http_build_query([ - "code" => $code, - "grant_type" => "authorization_code", - "redirect_uri" => $this->callback + 'code' => $code, + 'grant_type' => 'authorization_code', + 'redirect_uri' => $this->callback, ]) ), true); } @@ -100,24 +97,23 @@ class Yahoo extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $headers = [ - 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), + 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'get_token', + $this->endpoint.'get_token', $headers, \http_build_query([ - "refresh_token" => $refreshToken, - "grant_type" => "refresh_token", + 'refresh_token' => $refreshToken, + 'grant_type' => 'refresh_token', ]) ), true); @@ -129,8 +125,7 @@ class Yahoo extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -141,8 +136,7 @@ class Yahoo extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -157,20 +151,18 @@ class Yahoo extends OAuth2 * * If present, the email is verified. This was verfied through a manual Yahoo sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -181,8 +173,7 @@ class Yahoo extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) @@ -191,7 +182,7 @@ class Yahoo extends OAuth2 $this->user = \json_decode($this->request( 'GET', $this->resourceEndpoint, - ['Authorization: Bearer ' . \urlencode($accessToken)] + ['Authorization: Bearer '.\urlencode($accessToken)] ), true); } diff --git a/src/Appwrite/Auth/OAuth2/Yammer.php b/src/Appwrite/Auth/OAuth2/Yammer.php index 9e1827bc58..c6d1ba2837 100644 --- a/src/Appwrite/Auth/OAuth2/Yammer.php +++ b/src/Appwrite/Auth/OAuth2/Yammer.php @@ -37,18 +37,17 @@ class Yammer extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . 'oauth2/authorize?' . + return $this->endpoint.'oauth2/authorize?'. \http_build_query([ 'client_id' => $this->appID, 'response_type' => 'code', 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array @@ -57,13 +56,13 @@ class Yammer extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'access_token?', + $this->endpoint.'access_token?', $headers, \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'code' => $code, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -72,8 +71,7 @@ class Yammer extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array @@ -81,13 +79,13 @@ class Yammer extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . 'access_token?', + $this->endpoint.'access_token?', $headers, \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token' + 'grant_type' => 'refresh_token', ]) ), true); @@ -99,8 +97,7 @@ class Yammer extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -111,8 +108,7 @@ class Yammer extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -127,20 +123,18 @@ class Yammer extends OAuth2 * * If present, the email is verified. This was verfied through a manual Yammer sign up process * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return !empty($email); + return ! empty($email); } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -151,14 +145,13 @@ class Yammer extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; $user = $this->request('GET', 'https://www.yammer.com/api/v1/users/current.json', $headers); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Yandex.php b/src/Appwrite/Auth/OAuth2/Yandex.php index a6a2e2e550..13e1fb4dfc 100644 --- a/src/Appwrite/Auth/OAuth2/Yandex.php +++ b/src/Appwrite/Auth/OAuth2/Yandex.php @@ -8,7 +8,6 @@ use Appwrite\Auth\OAuth2; // https://tech.yandex.com/passport/doc/dg/reference/request-docpage/ // https://tech.yandex.com/oauth/doc/dg/reference/web-client-docpage/ - class Yandex extends OAuth2 { /** @@ -35,8 +34,7 @@ class Yandex extends OAuth2 } /** - * @param string $state - * + * @param string $state * @return array */ public function parseState(string $state) @@ -44,30 +42,28 @@ class Yandex extends OAuth2 return \json_decode(\html_entity_decode($state), true); } - /** * @return string */ public function getLoginURL(): string { - return 'https://oauth.yandex.com/authorize?' . \http_build_query([ + return 'https://oauth.yandex.com/authorize?'.\http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state) + 'state' => \json_encode($this->state), ]); } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { $headers = [ - 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), + 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -76,7 +72,7 @@ class Yandex extends OAuth2 $headers, \http_build_query([ 'code' => $code, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); } @@ -85,14 +81,13 @@ class Yandex extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { $headers = [ - 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), + 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -101,7 +96,7 @@ class Yandex extends OAuth2 $headers, \http_build_query([ 'refresh_token' => $refreshToken, - 'grant_type' => 'authorization_code' + 'grant_type' => 'authorization_code', ]) ), true); @@ -113,8 +108,7 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -125,8 +119,7 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -139,8 +132,7 @@ class Yandex extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -149,8 +141,7 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string @@ -161,19 +152,19 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://login.yandex.ru/info?' . \http_build_query([ + $user = $this->request('GET', 'https://login.yandex.ru/info?'.\http_build_query([ 'format' => 'json', - 'oauth_token' => $accessToken + 'oauth_token' => $accessToken, ])); $this->user = \json_decode($user, true); } + return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Zoom.php b/src/Appwrite/Auth/OAuth2/Zoom.php index 9dad22212a..01ade69a48 100644 --- a/src/Appwrite/Auth/OAuth2/Zoom.php +++ b/src/Appwrite/Auth/OAuth2/Zoom.php @@ -30,7 +30,7 @@ class Zoom extends OAuth2 * @var array */ protected array $scopes = [ - 'user_info:read' + 'user_info:read', ]; /** @@ -46,7 +46,7 @@ class Zoom extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint . '/oauth/authorize?' . \http_build_query([ + return $this->endpoint.'/oauth/authorize?'.\http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', @@ -56,22 +56,21 @@ class Zoom extends OAuth2 } /** - * @param string $code - * + * @param string $code * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { - $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; + $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', $headers, \http_build_query([ 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callback, - 'code' => $code + 'code' => $code, ]) ), true); } @@ -80,16 +79,15 @@ class Zoom extends OAuth2 } /** - * @param string $refreshToken - * + * @param string $refreshToken * @return array */ public function refreshTokens(string $refreshToken): array { - $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; + $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint . '/oauth/token', + $this->endpoint.'/oauth/token', $headers, \http_build_query([ 'grant_type' => 'refresh_token', @@ -105,8 +103,7 @@ class Zoom extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserID(string $accessToken): string @@ -117,8 +114,7 @@ class Zoom extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserEmail(string $accessToken): string @@ -133,8 +129,7 @@ class Zoom extends OAuth2 * * @link https://marketplace.zoom.us/docs/api-reference/zoom-api/methods/#operation/user * - * @param string $accessToken - * + * @param string $accessToken * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -149,26 +144,24 @@ class Zoom extends OAuth2 } /** - * @param string $accessToken - * + * @param string $accessToken * @return string */ public function getUserName(string $accessToken): string { $response = $this->getUser($accessToken); - return ($response['first_name'] ?? '') . ' ' . ($response['last_name'] ?? ''); + return ($response['first_name'] ?? '').' '.($response['last_name'] ?? ''); } /** - * @param string $accessToken - * + * @param string $accessToken * @return array */ protected function getUser(string $accessToken) { $headers = [ - 'Authorization: Bearer ' . \urlencode($accessToken) + 'Authorization: Bearer '.\urlencode($accessToken), ]; if (empty($this->user)) { diff --git a/src/Appwrite/Auth/Validator/Password.php b/src/Appwrite/Auth/Validator/Password.php index 93a9f74114..e997d03f81 100644 --- a/src/Appwrite/Auth/Validator/Password.php +++ b/src/Appwrite/Auth/Validator/Password.php @@ -26,13 +26,12 @@ class Password extends Validator /** * Is valid. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($value): bool { - if (!\is_string($value)) { + if (! \is_string($value)) { return false; } diff --git a/src/Appwrite/Auth/Validator/PasswordDictionary.php b/src/Appwrite/Auth/Validator/PasswordDictionary.php index 003d68bc73..27feeeca36 100644 --- a/src/Appwrite/Auth/Validator/PasswordDictionary.php +++ b/src/Appwrite/Auth/Validator/PasswordDictionary.php @@ -10,6 +10,7 @@ namespace Appwrite\Auth\Validator; class PasswordDictionary extends Password { protected array $dictionary; + protected bool $enabled; public function __construct(array $dictionary, bool $enabled = false) @@ -33,19 +34,19 @@ class PasswordDictionary extends Password /** * Is valid. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($value): bool { - if (!parent::isValid($value)) { + if (! parent::isValid($value)) { return false; } if ($this->enabled && array_key_exists($value, $this->dictionary)) { return false; } + return true; } diff --git a/src/Appwrite/Auth/Validator/PasswordHistory.php b/src/Appwrite/Auth/Validator/PasswordHistory.php index 8cfabf4666..d78abe6689 100644 --- a/src/Appwrite/Auth/Validator/PasswordHistory.php +++ b/src/Appwrite/Auth/Validator/PasswordHistory.php @@ -12,7 +12,9 @@ use Appwrite\Auth\Auth; class PasswordHistory extends Password { protected array $history; + protected string $algo; + protected array $algoOptions; public function __construct(array $history, string $algo, array $algoOptions = []) @@ -37,8 +39,7 @@ class PasswordHistory extends Password /** * Is valid. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($value): bool @@ -48,6 +49,7 @@ class PasswordHistory extends Password return false; } } + return true; } diff --git a/src/Appwrite/Auth/Validator/PersonalData.php b/src/Appwrite/Auth/Validator/PersonalData.php index 6f8ed0a8c9..911d8f5515 100644 --- a/src/Appwrite/Auth/Validator/PersonalData.php +++ b/src/Appwrite/Auth/Validator/PersonalData.php @@ -31,17 +31,16 @@ class PersonalData extends Password /** * Is valid. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($password): bool { - if (!parent::isValid($password)) { + if (! parent::isValid($password)) { return false; } - if (!$this->strict) { + if (! $this->strict) { $password = strtolower($password); $this->userId = strtolower($this->userId); $this->email = strtolower($this->email); diff --git a/src/Appwrite/Auth/Validator/Phone.php b/src/Appwrite/Auth/Validator/Phone.php index 32c3ca3398..49d78ac8c6 100644 --- a/src/Appwrite/Auth/Validator/Phone.php +++ b/src/Appwrite/Auth/Validator/Phone.php @@ -26,13 +26,12 @@ class Phone extends Validator /** * Is valid. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($value): bool { - return is_string($value) && !!\preg_match('/^\+[1-9]\d{1,14}$/', $value); + return is_string($value) && (bool) \preg_match('/^\+[1-9]\d{1,14}$/', $value); } /** diff --git a/src/Appwrite/Detector/Detector.php b/src/Appwrite/Detector/Detector.php index 62f7a0a04b..ed1be7325b 100644 --- a/src/Appwrite/Detector/Detector.php +++ b/src/Appwrite/Detector/Detector.php @@ -17,7 +17,7 @@ class Detector protected $detctor; /** - * @param string $userAgent + * @param string $userAgent */ public function __construct(string $userAgent) { @@ -54,7 +54,7 @@ class Detector 'type' => 'desktop', 'short_name' => 'cli', 'name' => 'Appwrite CLI', - 'version' => $version + 'version' => $version, ]; } else { $client = $this->getDetector()->getClient(); @@ -89,7 +89,7 @@ class Detector */ protected function getDetector(): DeviceDetector { - if (!$this->detctor) { + if (! $this->detctor) { $this->detctor = new DeviceDetector($this->userAgent); $this->detctor->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) $this->detctor->parse(); @@ -103,7 +103,7 @@ class Detector * It is needed if we want bots to be processed as a simple clients. So we can detect if it is mobile client, * or desktop, or enything else. By default all this information is not retrieved for the bots. * - * @param bool $skip + * @param bool $skip */ public function skipBotDetection(bool $skip = true): void { diff --git a/src/Appwrite/Docker/Compose.php b/src/Appwrite/Docker/Compose.php index 64441805de..0b4a8b16b9 100644 --- a/src/Appwrite/Docker/Compose.php +++ b/src/Appwrite/Docker/Compose.php @@ -13,7 +13,7 @@ class Compose protected $compose = []; /** - * @var string $data + * @var string */ public function __construct(string $data) { @@ -48,7 +48,7 @@ class Compose */ public function getService(string $name): Service { - if (!isset($this->compose['services'][$name])) { + if (! isset($this->compose['services'][$name])) { throw new Exception('Service not found'); } diff --git a/src/Appwrite/Docker/Compose/Service.php b/src/Appwrite/Docker/Compose/Service.php index a3f9c91253..32c12b82b1 100644 --- a/src/Appwrite/Docker/Compose/Service.php +++ b/src/Appwrite/Docker/Compose/Service.php @@ -12,7 +12,7 @@ class Service protected $service = []; /** - * @var string $path + * @var string */ public function __construct(array $service) { @@ -54,7 +54,8 @@ class Service public function getImageVersion(): string { $image = $this->getImage(); - return substr($image, ((int)strpos($image, ':')) + 1); + + return substr($image, ((int) strpos($image, ':')) + 1); } /** diff --git a/src/Appwrite/Docker/Env.php b/src/Appwrite/Docker/Env.php index bce12a95e6..6351ce4f78 100644 --- a/src/Appwrite/Docker/Env.php +++ b/src/Appwrite/Docker/Env.php @@ -2,8 +2,6 @@ namespace Appwrite\Docker; -use Exception; - class Env { /** @@ -12,7 +10,7 @@ class Env protected $vars = []; /** - * @var string $data + * @var string */ public function __construct(string $data) { @@ -30,9 +28,8 @@ class Env } /** - * @param string $key - * @param mixed $value - * + * @param string $key + * @param mixed $value * @return $this */ public function setVar(string $key, $value): self @@ -43,8 +40,7 @@ class Env } /** - * @param string $key - * + * @param string $key * @return string */ public function getVar(string $key): string @@ -70,7 +66,7 @@ class Env $output = ''; foreach ($this->vars as $key => $value) { - $output .= $key . '=' . $value . "\n"; + $output .= $key.'='.$value."\n"; } return $output; diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index 254f7c294a..da396bba17 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -7,8 +7,11 @@ use Resque; class Audit extends Event { protected string $resource = ''; + protected string $mode = ''; + protected string $userAgent = ''; + protected string $ip = ''; public function __construct() @@ -19,7 +22,7 @@ class Audit extends Event /** * Set resource for this audit event. * - * @param string $resource + * @param string $resource * @return self */ public function setResource(string $resource): self @@ -42,7 +45,7 @@ class Audit extends Event /** * Set mode for this audit event * - * @param string $mode + * @param string $mode * @return self */ public function setMode(string $mode): self @@ -65,7 +68,7 @@ class Audit extends Event /** * Set user agent for this audit event. * - * @param string $userAgent + * @param string $userAgent * @return self */ public function setUserAgent(string $userAgent): self @@ -88,7 +91,7 @@ class Audit extends Event /** * Set IP for this audit event. * - * @param string $ip + * @param string $ip * @return self */ public function setIP(string $ip): self @@ -112,6 +115,7 @@ class Audit extends Event * Executes the event and sends it to the audit worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index 4d4b338118..92e4659dd7 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -8,7 +8,9 @@ use Utopia\Database\Document; class Build extends Event { protected string $type = ''; + protected ?Document $resource = null; + protected ?Document $deployment = null; public function __construct() @@ -19,7 +21,7 @@ class Build extends Event /** * Sets resource document for the build event. * - * @param Document $resource + * @param Document $resource * @return self */ public function setResource(Document $resource): self @@ -42,7 +44,7 @@ class Build extends Event /** * Sets deployment for the build event. * - * @param Document $deployment + * @param Document $deployment * @return self */ public function setDeployment(Document $deployment): self @@ -65,7 +67,7 @@ class Build extends Event /** * Sets type for the build event. * - * @param string $type Can be `BUILD_TYPE_DEPLOYMENT` or `BUILD_TYPE_RETRY`. + * @param string $type Can be `BUILD_TYPE_DEPLOYMENT` or `BUILD_TYPE_RETRY`. * @return self */ public function setType(string $type): self @@ -89,6 +91,7 @@ class Build extends Event * Executes the function event and sends it to the functions worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -97,7 +100,7 @@ class Build extends Event 'project' => $this->project, 'resource' => $this->resource, 'deployment' => $this->deployment, - 'type' => $this->type + 'type' => $this->type, ]); } } diff --git a/src/Appwrite/Event/Certificate.php b/src/Appwrite/Event/Certificate.php index d3d9091804..c39adbed8f 100644 --- a/src/Appwrite/Event/Certificate.php +++ b/src/Appwrite/Event/Certificate.php @@ -8,6 +8,7 @@ use Utopia\Database\Document; class Certificate extends Event { protected bool $skipRenewCheck = false; + protected ?Document $domain = null; public function __construct() @@ -18,7 +19,7 @@ class Certificate extends Event /** * Set domain for this certificates event. * - * @param Document $domain + * @param Document $domain * @return self */ public function setDomain(Document $domain): self @@ -41,7 +42,7 @@ class Certificate extends Event /** * Set if the certificate needs to be validated. * - * @param bool $skipRenewCheck + * @param bool $skipRenewCheck * @return self */ public function setSkipRenewCheck(bool $skipRenewCheck): self @@ -65,6 +66,7 @@ class Certificate extends Event * Executes the event and sends it to the certificates worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -72,7 +74,7 @@ class Certificate extends Event return Resque::enqueue($this->queue, $this->class, [ 'project' => $this->project, 'domain' => $this->domain, - 'skipRenewCheck' => $this->skipRenewCheck + 'skipRenewCheck' => $this->skipRenewCheck, ]); } } diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index 1822f06c71..cc83263d71 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -8,8 +8,11 @@ use Utopia\Database\Document; class Database extends Event { protected string $type = ''; + protected ?Document $database = null; + protected ?Document $collection = null; + protected ?Document $document = null; public function __construct() @@ -20,7 +23,7 @@ class Database extends Event /** * Sets the type for this database event (use the constants starting with DATABASE_TYPE_*). * - * @param string $type + * @param string $type * @return self */ public function setType(string $type): self @@ -32,6 +35,7 @@ class Database extends Event /** * Returns the set type for the database event. + * * @return string */ public function getType(): string @@ -42,19 +46,20 @@ class Database extends Event /** * Set the database for this event * - * @param Document $database + * @param Document $database * @return self */ public function setDatabase(Document $database): self { $this->database = $database; + return $this; } /** * Set the collection for this database event. * - * @param Document $collection + * @param Document $collection * @return self */ public function setCollection(Document $collection): self @@ -77,7 +82,7 @@ class Database extends Event /** * Set the document for this database event. * - * @param Document $document + * @param Document $document * @return self */ public function setDocument(Document $document): self @@ -89,6 +94,7 @@ class Database extends Event /** * Returns set document for this database event. + * * @return null|Document */ public function getDocument(): ?Document @@ -100,6 +106,7 @@ class Database extends Event * Executes the event and send it to the database worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -111,7 +118,7 @@ class Database extends Event 'collection' => $this->collection, 'document' => $this->document, 'database' => $this->database, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), ]); } } diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index d1519121a6..dee01ed6bf 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -8,11 +8,14 @@ use Utopia\Database\Document; class Delete extends Event { protected string $type = ''; - protected ?Document $document = null; - protected ?string $resource = null; - protected ?string $datetime = null; - protected ?string $hourlyUsageRetentionDatetime = null; + protected ?Document $document = null; + + protected ?string $resource = null; + + protected ?string $datetime = null; + + protected ?string $hourlyUsageRetentionDatetime = null; public function __construct() { @@ -22,7 +25,7 @@ class Delete extends Event /** * Sets the type for the delete event (use the constants starting with DELETE_TYPE_*). * - * @param string $type + * @param string $type * @return self */ public function setType(string $type): self @@ -45,31 +48,33 @@ class Delete extends Event /** * set Datetime. * - * @param string $datetime + * @param string $datetime * @return self */ public function setDatetime(string $datetime): self { $this->datetime = $datetime; + return $this; } /** * Sets datetime for 1h interval. * - * @param string $datetime + * @param string $datetime * @return self */ public function setUsageRetentionHourlyDateTime(string $datetime): self { $this->hourlyUsageRetentionDatetime = $datetime; + return $this; } /** * Sets the document for the delete event. * - * @param Document $document + * @param Document $document * @return self */ public function setDocument(Document $document): self @@ -92,7 +97,7 @@ class Delete extends Event /** * Sets the resource for the delete event. * - * @param string $resource + * @param string $resource * @return self */ public function setResource(string $resource): self @@ -112,11 +117,11 @@ class Delete extends Event return $this->document; } - /** * Executes this event and sends it to the deletes worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 23dde49637..0000cc482d 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -9,51 +9,70 @@ use Utopia\Database\Document; class Event { public const DATABASE_QUEUE_NAME = 'v1-database'; + public const DATABASE_CLASS_NAME = 'DatabaseV1'; public const DELETE_QUEUE_NAME = 'v1-deletes'; + public const DELETE_CLASS_NAME = 'DeletesV1'; public const AUDITS_QUEUE_NAME = 'v1-audits'; + public const AUDITS_CLASS_NAME = 'AuditsV1'; public const MAILS_QUEUE_NAME = 'v1-mails'; + public const MAILS_CLASS_NAME = 'MailsV1'; public const FUNCTIONS_QUEUE_NAME = 'v1-functions'; + public const FUNCTIONS_CLASS_NAME = 'FunctionsV1'; public const USAGE_QUEUE_NAME = 'v1-usage'; + public const USAGE_CLASS_NAME = 'UsageV1'; public const WEBHOOK_QUEUE_NAME = 'v1-webhooks'; + public const WEBHOOK_CLASS_NAME = 'WebhooksV1'; public const CERTIFICATES_QUEUE_NAME = 'v1-certificates'; + public const CERTIFICATES_CLASS_NAME = 'CertificatesV1'; public const BUILDS_QUEUE_NAME = 'v1-builds'; + public const BUILDS_CLASS_NAME = 'BuildsV1'; public const MESSAGING_QUEUE_NAME = 'v1-messaging'; + public const MESSAGING_CLASS_NAME = 'MessagingV1'; public const MIGRATIONS_QUEUE_NAME = 'v1-migrations'; + public const MIGRATIONS_CLASS_NAME = 'MigrationsV1'; protected string $queue = ''; + protected string $class = ''; + protected string $event = ''; + protected array $params = []; + protected array $payload = []; + protected array $context = []; + protected ?Document $project = null; + protected ?Document $user = null; + protected bool $paused = false; /** - * @param string $queue - * @param string $class + * @param string $queue + * @param string $class * @return void */ public function __construct(string $queue, string $class) @@ -65,7 +84,7 @@ class Event /** * Set queue used for this event. * - * @param string $queue + * @param string $queue * @return Event */ public function setQueue(string $queue): self @@ -87,7 +106,8 @@ class Event /** * Set event name used for this event. - * @param string $event + * + * @param string $event * @return Event */ public function setEvent(string $event): self @@ -110,7 +130,7 @@ class Event /** * Set project for this event. * - * @param Document $project + * @param Document $project * @return self */ public function setProject(Document $project): self @@ -133,7 +153,7 @@ class Event /** * Set user for this event. * - * @param Document $user + * @param Document $user * @return self */ public function setUser(Document $user): self @@ -156,7 +176,7 @@ class Event /** * Set payload for this event. * - * @param array $payload + * @param array $payload * @return self */ public function setPayload(array $payload): self @@ -179,8 +199,8 @@ class Event /** * Set context for this event. * - * @param string $key - * @param Document $context + * @param string $key + * @param Document $context * @return self */ public function setContext(string $key, Document $context): self @@ -193,8 +213,7 @@ class Event /** * Get context for this event. * - * @param string $key - * + * @param string $key * @return null|Document */ public function getContext(string $key): ?Document @@ -204,7 +223,8 @@ class Event /** * Set class used for this event. - * @param string $class + * + * @param string $class * @return self */ public function setClass(string $class): self @@ -227,8 +247,8 @@ class Event /** * Set param of event. * - * @param string $key - * @param mixed $value + * @param string $key + * @param mixed $value * @return self */ public function setParam(string $key, mixed $value): self @@ -241,7 +261,7 @@ class Event /** * Get param of event. * - * @param string $key + * @param string $key * @return mixed */ public function getParam(string $key): mixed @@ -263,6 +283,7 @@ class Event * Execute Event. * * @return string|bool + * * @throws InvalidArgumentException */ public function trigger(): string|bool @@ -276,7 +297,7 @@ class Event 'user' => $this->user, 'payload' => $this->payload, 'context' => $this->context, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), ]); } @@ -295,7 +316,7 @@ class Event /** * Parses event pattern and returns the parts in their respective section. * - * @param string $pattern + * @param string $pattern * @return array */ public static function parseEventPattern(string $pattern): array @@ -324,13 +345,13 @@ class Event } } - if ($hasSubResource && !$hasSubSubResource) { + if ($hasSubResource && ! $hasSubSubResource) { if ($count === 6) { $attribute = $parts[5]; } } - if (!$hasSubResource) { + if (! $hasSubResource) { if ($count === 4) { $attribute = $parts[3]; } @@ -342,7 +363,7 @@ class Event $subSubResource ??= false; $attribute ??= false; $action = match (true) { - !$hasSubResource && $count > 2 => $parts[2], + ! $hasSubResource && $count > 2 => $parts[2], $hasSubSubResource => $parts[6] ?? false, $hasSubResource && $count > 4 => $parts[4], default => false @@ -363,9 +384,10 @@ class Event /** * Generates all possible events from a pattern. * - * @param string $pattern - * @param array $params + * @param string $pattern + * @param array $params * @return array + * * @throws \InvalidArgumentException */ public static function generateEvents(string $pattern, array $params = []): array @@ -386,15 +408,15 @@ class Event $action = $parsed['action']; $attribute = $parsed['attribute']; - if ($resource && !\in_array(\trim($resource, "\[\]"), $paramKeys)) { + if ($resource && ! \in_array(\trim($resource, "\[\]"), $paramKeys)) { throw new InvalidArgumentException("{$resource} is missing from the params."); } - if ($subResource && !\in_array(\trim($subResource, "\[\]"), $paramKeys)) { + if ($subResource && ! \in_array(\trim($subResource, "\[\]"), $paramKeys)) { throw new InvalidArgumentException("{$subResource} is missing from the params."); } - if ($subSubResource && !\in_array(\trim($subSubResource, "\[\]"), $paramKeys)) { + if ($subSubResource && ! \in_array(\trim($subSubResource, "\[\]"), $paramKeys)) { throw new InvalidArgumentException("{$subSubResource} is missing from the params."); } @@ -448,9 +470,9 @@ class Event if ($subCurrent === $current || $subCurrent === $key) { continue; } - $filtered1 = \array_filter($paramKeys, fn(string $k) => $k === $subCurrent); + $filtered1 = \array_filter($paramKeys, fn (string $k) => $k === $subCurrent); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered1, '*', $eventPattern)); - $filtered2 = \array_filter($paramKeys, fn(string $k) => $k === $current); + $filtered2 = \array_filter($paramKeys, fn (string $k) => $k === $current); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered2, '*', \str_replace($filtered1, '*', $eventPattern))); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered2, '*', $eventPattern)); } @@ -458,7 +480,7 @@ class Event if ($current === $key) { continue; } - $filtered = \array_filter($paramKeys, fn(string $k) => $k === $current); + $filtered = \array_filter($paramKeys, fn (string $k) => $k === $current); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered, '*', $eventPattern)); } } diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index d121b47a4a..dea2381cda 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -9,9 +9,13 @@ use Utopia\Queue\Connection; class Func extends Event { protected string $jwt = ''; + protected string $type = ''; + protected string $data = ''; + protected ?Document $function = null; + protected ?Document $execution = null; public function __construct(protected Connection $connection) @@ -22,7 +26,7 @@ class Func extends Event /** * Sets function document for the function event. * - * @param Document $function + * @param Document $function * @return self */ public function setFunction(Document $function): self @@ -45,7 +49,7 @@ class Func extends Event /** * Sets execution for the function event. * - * @param Document $execution + * @param Document $execution * @return self */ public function setExecution(Document $execution): self @@ -68,7 +72,7 @@ class Func extends Event /** * Sets type for the function event. * - * @param string $type Can be `schedule`, `event` or `http`. + * @param string $type Can be `schedule`, `event` or `http`. * @return self */ public function setType(string $type): self @@ -91,7 +95,7 @@ class Func extends Event /** * Sets custom data for the function event. * - * @param string $data + * @param string $data * @return self */ public function setData(string $data): self @@ -114,7 +118,7 @@ class Func extends Event /** * Sets JWT for the function event. * - * @param string $jwt + * @param string $jwt * @return self */ public function setJWT(string $jwt): self @@ -138,6 +142,7 @@ class Func extends Event * Executes the function event and sends it to the functions worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -166,10 +171,8 @@ class Func extends Event /** * Generate a function event from a base event * - * @param Event $event - * + * @param Event $event * @return self - * */ public function from(Event $event): self { @@ -178,6 +181,7 @@ class Func extends Event $this->payload = $event->getPayload(); $this->event = $event->getEvent(); $this->params = $event->getParams(); + return $this; } } diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index 37b42704c5..68a6cfe2a3 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -3,15 +3,19 @@ namespace Appwrite\Event; use Resque; -use Utopia\Database\Document; class Mail extends Event { protected string $recipient = ''; + protected string $from = ''; + protected string $name = ''; + protected string $subject = ''; + protected string $body = ''; + protected array $smtp = []; public function __construct() @@ -22,7 +26,7 @@ class Mail extends Event /** * Sets subject for the mail event. * - * @param string $subject + * @param string $subject * @return self */ public function setSubject(string $subject): self @@ -45,7 +49,7 @@ class Mail extends Event /** * Sets recipient for the mail event. * - * @param string $recipient + * @param string $recipient * @return self */ public function setRecipient(string $recipient): self @@ -68,7 +72,7 @@ class Mail extends Event /** * Sets from for the mail event. * - * @param string $from + * @param string $from * @return self */ public function setFrom(string $from): self @@ -91,7 +95,7 @@ class Mail extends Event /** * Sets body for the mail event. * - * @param string $body + * @param string $body * @return self */ public function setBody(string $body): self @@ -114,7 +118,7 @@ class Mail extends Event /** * Sets name for the mail event. * - * @param string $name + * @param string $name * @return self */ public function setName(string $name): self @@ -137,12 +141,13 @@ class Mail extends Event /** * Set SMTP Host * - * @param string $host + * @param string $host * @return self */ public function setSmtpHost(string $host): self { $this->smtp['host'] = $host; + return $this; } @@ -155,54 +160,59 @@ class Mail extends Event public function setSmtpPort(int $port): self { $this->smtp['port'] = $port; + return $this; } /** * Set SMTP username * - * @param string $username + * @param string $username * @return self */ public function setSmtpUsername(string $username): self { $this->smtp['username']; + return $this; } /** * Set SMTP password * - * @param string $password + * @param string $password * @return self */ public function setSmtpPassword(string $password): self { $this->smtp['password']; + return $this; } /** * Set SMTP sender email * - * @param string $senderEmail + * @param string $senderEmail * @return self */ public function setSmtpSenderEmail(string $senderEmail): self { $this->smtp['senderEmail'] = $senderEmail; + return $this; } /** * Set SMTP reply to * - * @param string $replyTo + * @param string $replyTo * @return self */ public function setSmtpReplyTo(string $replyTo): self { $this->smtp['replyTo'] = $replyTo; + return $this; } @@ -219,7 +229,7 @@ class Mail extends Event /** * Get SMTP port * - * @return integer + * @return int */ public function getSmtpPort(): int { @@ -270,6 +280,7 @@ class Mail extends Event * Executes the event and sends it to the mails worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -281,7 +292,7 @@ class Mail extends Event 'subject' => $this->subject, 'body' => $this->body, 'smtp' => $this->smtp, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), ]); } } diff --git a/src/Appwrite/Event/Migration.php b/src/Appwrite/Event/Migration.php index 4d53f16796..ebe15483d0 100644 --- a/src/Appwrite/Event/Migration.php +++ b/src/Appwrite/Event/Migration.php @@ -10,6 +10,7 @@ use Utopia\Database\Document; class Migration extends Event { protected string $type = ''; + protected ?Document $migration = null; public function __construct() @@ -20,7 +21,7 @@ class Migration extends Event /** * Sets migration document for the migration event. * - * @param Document $migration + * @param Document $migration * @return self */ public function setMigration(Document $migration): self @@ -43,8 +44,7 @@ class Migration extends Event /** * Sets migration type for the migration event. * - * @param string $type - * + * @param string $type * @return self */ public function setType(string $type): self @@ -68,6 +68,7 @@ class Migration extends Event * Executes the migration event and sends it to the migrations worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -75,15 +76,16 @@ class Migration extends Event return Resque::enqueue($this->queue, $this->class, [ 'project' => $this->project, 'user' => $this->user, - 'migration' => $this->migration + 'migration' => $this->migration, ]); } /** * Schedules the migration event and schedules it in the migrations worker queue. * - * @param \DateTime|int $at + * @param \DateTime|int $at * @return void + * * @throws \Resque_Exception * @throws \ResqueScheduler_InvalidTimestampException */ @@ -92,7 +94,7 @@ class Migration extends Event ResqueScheduler::enqueueAt($at, $this->queue, $this->class, [ 'project' => $this->project, 'user' => $this->user, - 'migration' => $this->migration + 'migration' => $this->migration, ]); } } diff --git a/src/Appwrite/Event/Phone.php b/src/Appwrite/Event/Phone.php index 8baa5120c9..87bee4bc37 100644 --- a/src/Appwrite/Event/Phone.php +++ b/src/Appwrite/Event/Phone.php @@ -7,6 +7,7 @@ use Resque; class Phone extends Event { protected string $recipient = ''; + protected string $message = ''; public function __construct() @@ -17,7 +18,7 @@ class Phone extends Event /** * Sets recipient for the messaging event. * - * @param string $recipient + * @param string $recipient * @return self */ public function setRecipient(string $recipient): self @@ -40,7 +41,7 @@ class Phone extends Event /** * Sets url for the messaging event. * - * @param string $message + * @param string $message * @return self */ public function setMessage(string $message): self @@ -64,6 +65,7 @@ class Phone extends Event * Executes the event and sends it to the messaging worker. * * @return string|bool + * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -74,7 +76,7 @@ class Phone extends Event 'payload' => $this->payload, 'recipient' => $this->recipient, 'message' => $this->message, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), ]); } } diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index b302b88808..01f576896b 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -2,14 +2,15 @@ namespace Appwrite\Event; +use Utopia\Database\Document; use Utopia\Queue\Client; use Utopia\Queue\Connection; -use Utopia\Database\Document; class Usage extends Event { protected array $metrics = []; - protected array $reduce = []; + + protected array $reduce = []; public function __construct(protected Connection $connection) { @@ -19,7 +20,7 @@ class Usage extends Event /** * Add reduce. * - * @param Document $document + * @param Document $document * @return self */ public function addReduce(Document $document): self @@ -32,8 +33,8 @@ class Usage extends Event /** * Add metric. * - * @param string $key - * @param int $value + * @param string $key + * @param int $value * @return self */ public function addMetric(string $key, int $value): self @@ -57,7 +58,7 @@ class Usage extends Event return $client->enqueue([ 'project' => $this->getProject(), - 'reduce' => $this->reduce, + 'reduce' => $this->reduce, 'metrics' => $this->metrics, ]); } diff --git a/src/Appwrite/Event/Validator/Event.php b/src/Appwrite/Event/Validator/Event.php index 3f22900486..7e8ef316cc 100644 --- a/src/Appwrite/Event/Validator/Event.php +++ b/src/Appwrite/Event/Validator/Event.php @@ -27,8 +27,7 @@ class Event extends Validator /** * Is valid. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($value): bool @@ -48,6 +47,7 @@ class Event extends Validator if ($type == 'functions') { $this->message = 'Triggering a function on a function event is not allowed.'; + return false; } @@ -55,7 +55,7 @@ class Event extends Validator $hasSubResource = $count > 3 && ($events[$type]['$resource'] ?? false) && ($events[$type][$parts[2]]['$resource'] ?? false); $hasSubSubResource = $count > 5 && $hasSubResource && ($events[$type][$parts[2]][$parts[4]]['$resource'] ?? false); - if (!$type || !$resource) { + if (! $type || ! $resource) { return false; } @@ -72,13 +72,13 @@ class Event extends Validator } } - if ($hasSubResource && !$hasSubSubResource) { + if ($hasSubResource && ! $hasSubSubResource) { if ($count === 6) { $attribute = $parts[5]; } } - if (!$hasSubResource) { + if (! $hasSubResource) { if ($count === 4) { $attribute = $parts[3]; } @@ -91,36 +91,36 @@ class Event extends Validator $attribute ??= false; $action = match (true) { - !$hasSubResource && $count > 2 => $parts[2], + ! $hasSubResource && $count > 2 => $parts[2], $hasSubSubResource => $parts[6] ?? false, $hasSubResource && $count > 4 => $parts[4], default => false }; - if (!\array_key_exists($type, $events)) { + if (! \array_key_exists($type, $events)) { return false; } if ($subType) { - if ($action && !\array_key_exists($action, $events[$type][$subType])) { + if ($action && ! \array_key_exists($action, $events[$type][$subType])) { return false; } - if (!($subResource) || !\array_key_exists($subType, $events[$type])) { + if (! ($subResource) || ! \array_key_exists($subType, $events[$type])) { return false; } } else { - if ($action && !\array_key_exists($action, $events[$type])) { + if ($action && ! \array_key_exists($action, $events[$type])) { return false; } } if ($attribute) { if (($subType)) { - if (!\array_key_exists($attribute, $events[$type][$subType][$action])) { + if (! \array_key_exists($attribute, $events[$type][$subType][$action])) { return false; } } else { - if (!\array_key_exists($attribute, $events[$type][$action])) { + if (! \array_key_exists($attribute, $events[$type][$action])) { return false; } } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index d5803f5fbf..4b1be708c3 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -36,187 +36,295 @@ class Exception extends \Exception */ /** General */ - public const GENERAL_UNKNOWN = 'general_unknown'; - public const GENERAL_MOCK = 'general_mock'; - public const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; - public const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; - public const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; - public const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; - public const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; - public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; - public const GENERAL_PHONE_DISABLED = 'general_phone_disabled'; - public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; - public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; - public const GENERAL_QUERY_INVALID = 'general_query_invalid'; - public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; - public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; - public const GENERAL_SERVER_ERROR = 'general_server_error'; - public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; - public const GENERAL_CODES_DISABLED = 'general_codes_disabled'; - public const GENERAL_USAGE_DISABLED = 'general_usage_disabled'; + public const GENERAL_UNKNOWN = 'general_unknown'; + + public const GENERAL_MOCK = 'general_mock'; + + public const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; + + public const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; + + public const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; + + public const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; + + public const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; + + public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; + + public const GENERAL_PHONE_DISABLED = 'general_phone_disabled'; + + public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; + + public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; + + public const GENERAL_QUERY_INVALID = 'general_query_invalid'; + + public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; + + public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; + + public const GENERAL_SERVER_ERROR = 'general_server_error'; + + public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; + + public const GENERAL_CODES_DISABLED = 'general_codes_disabled'; + + public const GENERAL_USAGE_DISABLED = 'general_usage_disabled'; /** Users */ - public const USER_COUNT_EXCEEDED = 'user_count_exceeded'; - public const USER_JWT_INVALID = 'user_jwt_invalid'; - public const USER_ALREADY_EXISTS = 'user_already_exists'; - public const USER_BLOCKED = 'user_blocked'; - public const USER_INVALID_TOKEN = 'user_invalid_token'; - public const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; - public const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; - public const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; - public const USER_INVALID_CODE = 'user_invalid_code'; - public const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; + public const USER_COUNT_EXCEEDED = 'user_count_exceeded'; + + public const USER_JWT_INVALID = 'user_jwt_invalid'; + + public const USER_ALREADY_EXISTS = 'user_already_exists'; + + public const USER_BLOCKED = 'user_blocked'; + + public const USER_INVALID_TOKEN = 'user_invalid_token'; + + public const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; + + public const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; + + public const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; + + public const USER_INVALID_CODE = 'user_invalid_code'; + + public const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; + public const USER_ANONYMOUS_CONSOLE_PROHIBITED = 'user_anonymous_console_prohibited'; - public const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; - public const USER_NOT_FOUND = 'user_not_found'; - public const USER_PASSWORD_RECENTLY_USED = 'password_recently_used'; - public const USER_PASSWORD_PERSONAL_DATA = 'password_personal_data'; - public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; - public const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; - public const USER_SESSION_NOT_FOUND = 'user_session_not_found'; - public const USER_IDENTITY_NOT_FOUND = 'user_identity_not_found'; - public const USER_UNAUTHORIZED = 'user_unauthorized'; - public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; - public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists'; - public const USER_PHONE_NOT_FOUND = 'user_phone_not_found'; - public const USER_MISSING_ID = 'user_missing_id'; - public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; - public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; - public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; - public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; - public const USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; + + public const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; + + public const USER_NOT_FOUND = 'user_not_found'; + + public const USER_PASSWORD_RECENTLY_USED = 'password_recently_used'; + + public const USER_PASSWORD_PERSONAL_DATA = 'password_personal_data'; + + public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; + + public const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; + + public const USER_SESSION_NOT_FOUND = 'user_session_not_found'; + + public const USER_IDENTITY_NOT_FOUND = 'user_identity_not_found'; + + public const USER_UNAUTHORIZED = 'user_unauthorized'; + + public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; + + public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists'; + + public const USER_PHONE_NOT_FOUND = 'user_phone_not_found'; + + public const USER_MISSING_ID = 'user_missing_id'; + + public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; + + public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; + + public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; + + public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; + + public const USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; + /** Teams */ - public const TEAM_NOT_FOUND = 'team_not_found'; - public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; - public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; - public const TEAM_INVALID_SECRET = 'team_invalid_secret'; - public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; - public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; - public const TEAM_ALREADY_EXISTS = 'team_already_exists'; + public const TEAM_NOT_FOUND = 'team_not_found'; + + public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; + + public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; + + public const TEAM_INVALID_SECRET = 'team_invalid_secret'; + + public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; + + public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; + + public const TEAM_ALREADY_EXISTS = 'team_already_exists'; /** Membership */ - public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; - public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; + public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; + + public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; /** Avatars */ - public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; - public const AVATAR_NOT_FOUND = 'avatar_not_found'; - public const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; - public const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; - public const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; + public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; + + public const AVATAR_NOT_FOUND = 'avatar_not_found'; + + public const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; + + public const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; + + public const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; /** Storage */ - public const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; - public const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; - public const STORAGE_FILE_EMPTY = 'storage_file_empty'; - public const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; - public const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; - public const STORAGE_INVALID_FILE = 'storage_invalid_file'; - public const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; - public const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; - public const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; - public const STORAGE_INVALID_RANGE = 'storage_invalid_range'; - public const STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; + public const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; + + public const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; + + public const STORAGE_FILE_EMPTY = 'storage_file_empty'; + + public const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; + + public const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; + + public const STORAGE_INVALID_FILE = 'storage_invalid_file'; + + public const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; + + public const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; + + public const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; + + public const STORAGE_INVALID_RANGE = 'storage_invalid_range'; + + public const STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; /** Functions */ - public const FUNCTION_NOT_FOUND = 'function_not_found'; - public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; + public const FUNCTION_NOT_FOUND = 'function_not_found'; + + public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; /** Deployments */ - public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; + public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; /** Builds */ - public const BUILD_NOT_FOUND = 'build_not_found'; - public const BUILD_NOT_READY = 'build_not_ready'; - public const BUILD_IN_PROGRESS = 'build_in_progress'; + public const BUILD_NOT_FOUND = 'build_not_found'; + + public const BUILD_NOT_READY = 'build_not_ready'; + + public const BUILD_IN_PROGRESS = 'build_in_progress'; /** Execution */ - public const EXECUTION_NOT_FOUND = 'execution_not_found'; + public const EXECUTION_NOT_FOUND = 'execution_not_found'; /** Databases */ - public const DATABASE_NOT_FOUND = 'database_not_found'; - public const DATABASE_ALREADY_EXISTS = 'database_already_exists'; + public const DATABASE_NOT_FOUND = 'database_not_found'; + + public const DATABASE_ALREADY_EXISTS = 'database_already_exists'; /** Collections */ - public const COLLECTION_NOT_FOUND = 'collection_not_found'; - public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; - public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + public const COLLECTION_NOT_FOUND = 'collection_not_found'; + + public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; + + public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; /** Documents */ - public const DOCUMENT_NOT_FOUND = 'document_not_found'; - public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; - public const DOCUMENT_MISSING_DATA = 'document_missing_data'; - public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; - public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; - public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; - public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; + public const DOCUMENT_NOT_FOUND = 'document_not_found'; + + public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; + + public const DOCUMENT_MISSING_DATA = 'document_missing_data'; + + public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; + + public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; + + public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; + + public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; /** Attribute */ - public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; - public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; - public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; - public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; - public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; - public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; - public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; - public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; - public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; + public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; + + public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; + + public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; + + public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; + + public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; + + public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; + + public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; + + public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; + + public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; /** Indexes */ - public const INDEX_NOT_FOUND = 'index_not_found'; - public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; - public const INDEX_ALREADY_EXISTS = 'index_already_exists'; - public const INDEX_INVALID = 'index_invalid'; + public const INDEX_NOT_FOUND = 'index_not_found'; + + public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; + + public const INDEX_ALREADY_EXISTS = 'index_already_exists'; + + public const INDEX_INVALID = 'index_invalid'; /** Projects */ - public const PROJECT_NOT_FOUND = 'project_not_found'; - public const PROJECT_UNKNOWN = 'project_unknown'; - public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; - public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; - public const PROJECT_ALREADY_EXISTS = 'project_already_exists'; - public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; - public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; - public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; - public const PROJECT_KEY_EXPIRED = 'project_key_expired'; + public const PROJECT_NOT_FOUND = 'project_not_found'; - public const PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid'; + public const PROJECT_UNKNOWN = 'project_unknown'; + + public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; + + public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; + + public const PROJECT_ALREADY_EXISTS = 'project_already_exists'; + + public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; + + public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; + + public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; + + public const PROJECT_KEY_EXPIRED = 'project_key_expired'; + + public const PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid'; public const PROJECT_TEMPLATE_DEFAULT_DELETION = 'project_template_default_deletion'; /** Webhooks */ - public const WEBHOOK_NOT_FOUND = 'webhook_not_found'; + public const WEBHOOK_NOT_FOUND = 'webhook_not_found'; /** Keys */ - public const KEY_NOT_FOUND = 'key_not_found'; + public const KEY_NOT_FOUND = 'key_not_found'; /** Variables */ - public const VARIABLE_NOT_FOUND = 'variable_not_found'; - public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; + public const VARIABLE_NOT_FOUND = 'variable_not_found'; + + public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; /** Platform */ - public const PLATFORM_NOT_FOUND = 'platform_not_found'; + public const PLATFORM_NOT_FOUND = 'platform_not_found'; /** Domain */ - public const DOMAIN_NOT_FOUND = 'domain_not_found'; - public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; - public const DOMAIN_FORBIDDEN = 'domain_forbidden'; - public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; - public const DOMAIN_TARGET_INVALID = 'domain_target_invalid'; + public const DOMAIN_NOT_FOUND = 'domain_not_found'; + + public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; + + public const DOMAIN_FORBIDDEN = 'domain_forbidden'; + + public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; + + public const DOMAIN_TARGET_INVALID = 'domain_target_invalid'; /** GraphqQL */ - public const GRAPHQL_NO_QUERY = 'graphql_no_query'; - public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; + public const GRAPHQL_NO_QUERY = 'graphql_no_query'; + + public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; /** Migrations */ - public const MIGRATION_NOT_FOUND = 'migration_not_found'; - public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists'; - public const MIGRATION_IN_PROGRESS = 'migration_in_progress'; + public const MIGRATION_NOT_FOUND = 'migration_not_found'; + + public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists'; + + public const MIGRATION_IN_PROGRESS = 'migration_in_progress'; /** Provider */ - public const PROVIDER_NOT_FOUND = 'provider_not_found'; - public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; + public const PROVIDER_NOT_FOUND = 'provider_not_found'; + + public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; protected $type = ''; + protected $errors = []; public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int $code = null, \Throwable $previous = null) @@ -248,8 +356,7 @@ class Exception extends \Exception /** * Set the type of the exception. * - * @param string $type - * + * @param string $type * @return void */ public function setType(string $type): void diff --git a/src/Appwrite/GraphQL/Promises/Adapter.php b/src/Appwrite/GraphQL/Promises/Adapter.php index 86270f2a8b..0051dbe612 100644 --- a/src/Appwrite/GraphQL/Promises/Adapter.php +++ b/src/Appwrite/GraphQL/Promises/Adapter.php @@ -22,14 +22,15 @@ abstract class Adapter implements PromiseAdapter /** * Converts a {@see Promise} into a {@see GQLPromise} * - * @param mixed $thenable + * @param mixed $thenable * @return GQLPromise + * * @throws \Exception */ public function convertThenable(mixed $thenable): GQLPromise { - if (!$thenable instanceof Promise) { - throw new \Exception('Expected instance of Promise got: ' . \gettype($thenable)); + if (! $thenable instanceof Promise) { + throw new \Exception('Expected instance of Promise got: '.\gettype($thenable)); } return new GQLPromise($thenable, $this); @@ -38,9 +39,9 @@ abstract class Adapter implements PromiseAdapter /** * Returns a promise that resolves when the passed in promise resolves. * - * @param GQLPromise $promise - * @param callable|null $onFulfilled - * @param callable|null $onRejected + * @param GQLPromise $promise + * @param callable|null $onFulfilled + * @param callable|null $onRejected * @return GQLPromise */ public function then( @@ -57,7 +58,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise with the given resolver function. * - * @param callable $resolver + * @param callable $resolver * @return GQLPromise */ abstract public function create(callable $resolver): GQLPromise; @@ -65,7 +66,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise that is fulfilled with the given value. * - * @param mixed $value + * @param mixed $value * @return GQLPromise */ abstract public function createFulfilled(mixed $value = null): GQLPromise; @@ -73,7 +74,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise that is rejected with the given reason. * - * @param mixed $reason + * @param mixed $reason * @return GQLPromise */ abstract public function createRejected(mixed $reason): GQLPromise; @@ -81,7 +82,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise that resolves when all passed in promises resolve. * - * @param array $promisesOrValues + * @param array $promisesOrValues * @return GQLPromise */ abstract public function all(array $promisesOrValues): GQLPromise; diff --git a/src/Appwrite/GraphQL/Resolvers.php b/src/Appwrite/GraphQL/Resolvers.php index c143a93554..3c5ba4b310 100644 --- a/src/Appwrite/GraphQL/Resolvers.php +++ b/src/Appwrite/GraphQL/Resolvers.php @@ -15,28 +15,28 @@ class Resolvers /** * Create a resolver for a given API {@see Route}. * - * @param App $utopia - * @param ?Route $route + * @param App $utopia + * @param ?Route $route * @return callable */ public static function api( App $utopia, ?Route $route, - ): callable { - return static fn($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $route, $args, $context, $info) { + ): callable + { + return static fn ($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $route, $args) { /** @var App $utopia */ /** @var Response $response */ /** @var Request $request */ - $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); $path = $route->getPath(); foreach ($args as $key => $value) { - if (\str_contains($path, '/:' . $key)) { - $path = \str_replace(':' . $key, $value, $path); + if (\str_contains($path, '/:'.$key)) { + $path = \str_replace(':'.$key, $value, $path); } } @@ -60,10 +60,10 @@ class Resolvers /** * Create a resolver for a document in a specified database and collection with a specific method type. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param string $methodType + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param string $methodType * @return callable */ public static function document( @@ -71,8 +71,9 @@ class Resolvers string $databaseId, string $collectionId, string $methodType, - ): callable { - return [self::class, 'document' . \ucfirst($methodType)]( + ): callable + { + return [self::class, 'document'.\ucfirst($methodType)]( $utopia, $databaseId, $collectionId @@ -82,10 +83,10 @@ class Resolvers /** * Create a resolver for getting a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url * @return callable */ public static function documentGet( @@ -93,9 +94,10 @@ class Resolvers string $databaseId, string $collectionId, callable $url, - ): callable { - return static fn($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $type, $args) { + ): callable + { + return static fn ($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -111,11 +113,11 @@ class Resolvers /** * Create a resolver for listing documents in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url - * @param callable $params + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url + * @param callable $params * @return callable */ public static function documentList( @@ -124,9 +126,10 @@ class Resolvers string $collectionId, callable $url, callable $params, - ): callable { - return static fn($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) { + ): callable + { + return static fn ($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -147,11 +150,11 @@ class Resolvers /** * Create a resolver for creating a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url - * @param callable $params + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url + * @param callable $params * @return callable */ public static function documentCreate( @@ -160,9 +163,10 @@ class Resolvers string $collectionId, callable $url, callable $params, - ): callable { - return static fn($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) { + ): callable + { + return static fn ($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -179,11 +183,11 @@ class Resolvers /** * Create a resolver for updating a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url - * @param callable $params + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url + * @param callable $params * @return callable */ public static function documentUpdate( @@ -192,9 +196,10 @@ class Resolvers string $collectionId, callable $url, callable $params, - ): callable { - return static fn($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) { + ): callable + { + return static fn ($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -211,10 +216,10 @@ class Resolvers /** * Create a resolver for deleting a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url * @return callable */ public static function documentDelete( @@ -222,9 +227,10 @@ class Resolvers string $databaseId, string $collectionId, callable $url, - ): callable { - return static fn($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $type, $args) { + ): callable + { + return static fn ($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -238,14 +244,15 @@ class Resolvers } /** - * @param App $utopia - * @param Request $request - * @param Response $response - * @param callable $resolve - * @param callable $reject - * @param callable|null $beforeResolve - * @param callable|null $beforeReject + * @param App $utopia + * @param Request $request + * @param Response $response + * @param callable $resolve + * @param callable $reject + * @param callable|null $beforeResolve + * @param callable|null $beforeReject * @return void + * * @throws Exception */ private static function resolve( @@ -263,7 +270,7 @@ class Resolvers } $request = clone $request; - $utopia->setResource('request', static fn() => $request); + $utopia->setResource('request', static fn () => $request); $response->setContentType(Response::CONTENT_TYPE_NULL); try { @@ -275,6 +282,7 @@ class Resolvers $e = $beforeReject($e); } $reject($e); + return; } @@ -288,6 +296,7 @@ class Resolvers message: $payload['message'], code: $response->getStatusCode() )); + return; } diff --git a/src/Appwrite/GraphQL/Schema.php b/src/Appwrite/GraphQL/Schema.php index 11f728e571..608369ef80 100644 --- a/src/Appwrite/GraphQL/Schema.php +++ b/src/Appwrite/GraphQL/Schema.php @@ -13,16 +13,17 @@ use Utopia\Route; class Schema { protected static ?GQLSchema $schema = null; + protected static array $dirty = []; /** - * - * @param App $utopia - * @param callable $complexity Function to calculate complexity - * @param callable $attributes Function to get attributes - * @param array $urls Array of functions to get urls for specific method types - * @param array $params Array of functions to build parameters for specific method types + * @param App $utopia + * @param callable $complexity Function to calculate complexity + * @param callable $attributes Function to get attributes + * @param array $urls Array of functions to get urls for specific method types + * @param array $params Array of functions to build parameters for specific method types * @return GQLSchema + * * @throws Exception */ public static function build( @@ -36,7 +37,7 @@ class Schema return $utopia; }); - if (!empty(self::$schema)) { + if (! empty(self::$schema)) { return self::$schema; } @@ -67,12 +68,12 @@ class Schema return static::$schema = new GQLSchema([ 'query' => new ObjectType([ 'name' => 'Query', - 'fields' => $queries + 'fields' => $queries, ]), 'mutation' => new ObjectType([ 'name' => 'Mutation', - 'fields' => $mutations - ]) + 'fields' => $mutations, + ]), ]); } @@ -80,9 +81,10 @@ class Schema * This function iterates all API routes and builds a GraphQL * schema defining types and resolvers for all response models. * - * @param App $utopia - * @param callable $complexity + * @param App $utopia + * @param callable $complexity * @return array + * * @throws Exception */ protected static function api(App $utopia, callable $complexity): array @@ -97,10 +99,9 @@ class Schema foreach ($utopia->getRoutes() as $routes) { foreach ($routes as $route) { /** @var Route $route */ - $namespace = $route->getLabel('sdk.namespace', ''); $method = $route->getLabel('sdk.method', ''); - $name = $namespace . \ucfirst($method); + $name = $namespace.\ucfirst($method); if (empty($name)) { continue; @@ -126,7 +127,7 @@ class Schema return [ 'query' => $queries, - 'mutation' => $mutations + 'mutation' => $mutations, ]; } @@ -134,12 +135,13 @@ class Schema * Iterates all of a projects attributes and builds GraphQL * queries and mutations for the collections they make up. * - * @param App $utopia - * @param callable $complexity - * @param callable $attributes - * @param array $urls - * @param array $params + * @param App $utopia + * @param callable $complexity + * @param callable $attributes + * @param array $urls + * @param array $params * @return array + * * @throws \Exception */ protected static function collections( @@ -155,7 +157,7 @@ class Schema $limit = 1000; $offset = 0; - while (!empty($attrs = $attributes($limit, $offset))) { + while (! empty($attrs = $attributes($limit, $offset))) { foreach ($attrs as $attr) { if ($attr['status'] !== 'available') { continue; @@ -182,7 +184,7 @@ class Schema $objectType = new ObjectType([ 'name' => $collectionId, 'fields' => \array_merge( - ["_id" => ['type' => Type::string()]], + ['_id' => ['type' => Type::string()]], $attributes ), ]); @@ -191,7 +193,7 @@ class Schema Mapper::args('mutate') ); - $queryFields[$collectionId . 'Get'] = [ + $queryFields[$collectionId.'Get'] = [ 'type' => $objectType, 'args' => Mapper::args('id'), 'resolve' => Resolvers::documentGet( @@ -199,9 +201,9 @@ class Schema $databaseId, $collectionId, $urls['get'], - ) + ), ]; - $queryFields[$collectionId . 'List'] = [ + $queryFields[$collectionId.'List'] = [ 'type' => Type::listOf($objectType), 'args' => Mapper::args('list'), 'resolve' => Resolvers::documentList( @@ -214,7 +216,7 @@ class Schema 'complexity' => $complexity, ]; - $mutationFields[$collectionId . 'Create'] = [ + $mutationFields[$collectionId.'Create'] = [ 'type' => $objectType, 'args' => $attributes, 'resolve' => Resolvers::documentCreate( @@ -223,14 +225,14 @@ class Schema $collectionId, $urls['create'], $params['create'], - ) + ), ]; - $mutationFields[$collectionId . 'Update'] = [ + $mutationFields[$collectionId.'Update'] = [ 'type' => $objectType, 'args' => \array_merge( Mapper::args('id'), \array_map( - fn($attr) => $attr['type'] = Type::getNullableType($attr['type']), + fn ($attr) => $attr['type'] = Type::getNullableType($attr['type']), $attributes ) ), @@ -240,9 +242,9 @@ class Schema $collectionId, $urls['update'], $params['update'], - ) + ), ]; - $mutationFields[$collectionId . 'Delete'] = [ + $mutationFields[$collectionId.'Delete'] = [ 'type' => Mapper::model('none'), 'args' => Mapper::args('id'), 'resolve' => Resolvers::documentDelete( @@ -250,7 +252,7 @@ class Schema $databaseId, $collectionId, $urls['delete'], - ) + ), ]; } $offset += $limit; @@ -258,7 +260,7 @@ class Schema return [ 'query' => $queryFields, - 'mutation' => $mutationFields + 'mutation' => $mutationFields, ]; } diff --git a/src/Appwrite/GraphQL/Types.php b/src/Appwrite/GraphQL/Types.php index 279cac2068..b20c4cb32e 100644 --- a/src/Appwrite/GraphQL/Types.php +++ b/src/Appwrite/GraphQL/Types.php @@ -22,6 +22,7 @@ class Types } $type = new Json(); Registry::set(Json::class, $type); + return $type; } @@ -37,6 +38,7 @@ class Types } $type = new Assoc(); Registry::set(Assoc::class, $type); + return $type; } @@ -52,6 +54,7 @@ class Types } $type = new InputFile(); Registry::set(InputFile::class, $type); + return $type; } } diff --git a/src/Appwrite/GraphQL/Types/Assoc.php b/src/Appwrite/GraphQL/Types/Assoc.php index a2099f9b22..58584ff60f 100644 --- a/src/Appwrite/GraphQL/Types/Assoc.php +++ b/src/Appwrite/GraphQL/Types/Assoc.php @@ -2,19 +2,13 @@ namespace Appwrite\GraphQL\Types; -use GraphQL\Language\AST\BooleanValueNode; -use GraphQL\Language\AST\FloatValueNode; -use GraphQL\Language\AST\IntValueNode; -use GraphQL\Language\AST\ListValueNode; use GraphQL\Language\AST\Node; -use GraphQL\Language\AST\ObjectValueNode; -use GraphQL\Language\AST\StringValueNode; -use GraphQL\Type\Definition\ScalarType; // https://github.com/webonyx/graphql-php/issues/129#issuecomment-309366803 class Assoc extends Json { public $name = 'Assoc'; + public $description = 'The `Assoc` scalar type represents associative array values.'; public function serialize($value) diff --git a/src/Appwrite/GraphQL/Types/InputFile.php b/src/Appwrite/GraphQL/Types/InputFile.php index 39fd4e23b3..6d55ab5359 100644 --- a/src/Appwrite/GraphQL/Types/InputFile.php +++ b/src/Appwrite/GraphQL/Types/InputFile.php @@ -9,6 +9,7 @@ use GraphQL\Type\Definition\ScalarType; class InputFile extends ScalarType { public $name = 'InputFile'; + public $description = 'The `InputFile` special type represents a file to be uploaded in the same HTTP request as specified by [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec).'; @@ -24,6 +25,6 @@ class InputFile extends ScalarType public function parseLiteral(Node $valueNode, ?array $variables = null) { - throw new Error('`InputFile` cannot be hardcoded in query, be sure to conform to GraphQL multipart request specification. Instead got: ' . $valueNode->kind, $valueNode); + throw new Error('`InputFile` cannot be hardcoded in query, be sure to conform to GraphQL multipart request specification. Instead got: '.$valueNode->kind, $valueNode); } } diff --git a/src/Appwrite/GraphQL/Types/Json.php b/src/Appwrite/GraphQL/Types/Json.php index 18d27322a1..305432cb90 100644 --- a/src/Appwrite/GraphQL/Types/Json.php +++ b/src/Appwrite/GraphQL/Types/Json.php @@ -15,6 +15,7 @@ use GraphQL\Type\Definition\ScalarType; class Json extends ScalarType { public $name = 'Json'; + public $description = 'The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).'; @@ -43,8 +44,9 @@ class Json extends ScalarType $value[$field->name->value] = $this->parseLiteral($field->value); } + return $value; - case ($valueNode instanceof ListValueNode): + case $valueNode instanceof ListValueNode: return array_map([$this, 'parseLiteral'], $valueNode->values); default: return null; diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 0be60d93dc..1c03074f23 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -16,7 +16,9 @@ use Utopia\Validator\Nullable; class Mapper { private static array $models = []; + private static array $args = []; + private static array $blacklist = [ '/v1/mock', '/v1/graphql', @@ -43,7 +45,7 @@ class Mapper 'permissions' => [ 'type' => Type::listOf(Type::nonNull(Type::string())), 'defaultValue' => [], - ] + ], ], ]; @@ -66,7 +68,7 @@ class Mapper /** * Get the registered default arguments for a given key. * - * @param string $key + * @param string $key * @return array */ public static function args(string $key): array @@ -87,7 +89,7 @@ class Mapper $names = $route->getLabel('sdk.response.model', 'none'); $models = \is_array($names) - ? \array_map(static fn($m) => static::$models[$m], $names) + ? \array_map(static fn ($m) => static::$models[$m], $names) : [static::$models[$names]]; foreach ($models as $model) { @@ -103,7 +105,7 @@ class Mapper $parameterType = Mapper::param( $utopia, $parameter['validator'], - !$parameter['optional'], + ! $parameter['optional'], $parameter['injections'] ); $params[$name] = [ @@ -116,7 +118,7 @@ class Mapper 'type' => $type, 'description' => $description, 'args' => $params, - 'resolve' => Resolvers::api($utopia, $route) + 'resolve' => Resolvers::api($utopia, $route), ]; if ($list) { @@ -130,7 +132,7 @@ class Mapper /** * Get a type from the registry, creating it if it does not already exist. * - * @param string $name + * @param string $name * @return Type */ public static function model(string $name): Type @@ -149,23 +151,23 @@ class Mapper 'description' => 'Additional data', 'resolve' => static function ($object, $args, $context, $info) { $data = \array_filter( - (array)$object, - fn($key) => !\str_starts_with($key, '_'), + (array) $object, + fn ($key) => ! \str_starts_with($key, '_'), ARRAY_FILTER_USE_KEY ); return \json_encode($data, JSON_FORCE_OBJECT); - } + }, ]; } // If model has no properties, explicitly add a 'status' field // because GraphQL requires at least 1 field per type. - if (!$model->isAny() && empty($model->getRules())) { + if (! $model->isAny() && empty($model->getRules())) { $fields['status'] = [ 'type' => Type::string(), 'description' => 'Status', - 'resolve' => static fn($object, $args, $context, $info) => 'OK', + 'resolve' => static fn ($object, $args, $context, $info) => 'OK', ]; } @@ -187,7 +189,7 @@ class Mapper 'description' => $rule['description'], ]; - if (!$rule['required']) { + if (! $rule['required']) { $fields[$escapedKey]['defaultValue'] = $rule['default']; } } @@ -205,11 +207,12 @@ class Mapper /** * Map a {@see Route} parameter to a GraphQL Type * - * @param App $utopia - * @param Validator|callable $validator - * @param bool $required - * @param array $injections + * @param App $utopia + * @param Validator|callable $validator + * @param bool $required + * @param array $injections * @return Type + * * @throws Exception */ public static function param( @@ -228,7 +231,7 @@ class Mapper $validator = $validator->getValidator(); } - switch ((!empty($validator)) ? $validator::class : '') { + switch ((! empty($validator)) ? $validator::class : '') { case 'Appwrite\Network\Validator\CNAME': case 'Appwrite\Task\Validator\Cron': case 'Appwrite\Utopia\Database\Validator\CustomId': @@ -300,7 +303,7 @@ class Mapper break; } - if ($required && !$isNullable) { + if ($required && ! $isNullable) { $type = Type::nonNull($type); } @@ -310,10 +313,11 @@ class Mapper /** * Map an {@see Attribute} to a GraphQL Type * - * @param string $type - * @param bool $array - * @param bool $required + * @param string $type + * @param bool $array + * @param bool $required * @return Type + * * @throws Exception */ public static function attribute(string $type, bool $array, bool $required): Type @@ -349,6 +353,7 @@ class Mapper } $complexModel = self::$models[$type]; + return self::model(\ucfirst($complexModel->getType())); } @@ -389,7 +394,7 @@ class Mapper return static::getHashOptionsImplementation($object); } - throw new Exception('Unknown union type: ' . $name); + throw new Exception('Unknown union type: '.$name); } private static function getAttributeImplementation(array $object): Type diff --git a/src/Appwrite/GraphQL/Types/Registry.php b/src/Appwrite/GraphQL/Types/Registry.php index cd40d5c3e4..325766bb67 100644 --- a/src/Appwrite/GraphQL/Types/Registry.php +++ b/src/Appwrite/GraphQL/Types/Registry.php @@ -11,7 +11,7 @@ class Registry /** * Check if a type exists in the registry. * - * @param string $type + * @param string $type * @return bool */ public static function has(string $type): bool @@ -22,7 +22,7 @@ class Registry /** * Get a type from the registry. * - * @param string $type + * @param string $type * @return Type */ public static function get(string $type): Type @@ -33,8 +33,8 @@ class Registry /** * Set a type in the registry. * - * @param string $type - * @param Type $typeObject + * @param string $type + * @param Type $typeObject */ public static function set(string $type, Type $typeObject): void { diff --git a/src/Appwrite/Messaging/Adapter.php b/src/Appwrite/Messaging/Adapter.php index 27dd7f68eb..794fd9b3ed 100644 --- a/src/Appwrite/Messaging/Adapter.php +++ b/src/Appwrite/Messaging/Adapter.php @@ -5,6 +5,8 @@ namespace Appwrite\Messaging; abstract class Adapter { abstract public function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void; + abstract public function unsubscribe(mixed $identifier): void; + abstract public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void; } diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 33fe484c13..2824f948d7 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -2,10 +2,10 @@ namespace Appwrite\Messaging\Adapter; -use Utopia\Database\DateTime; -use Utopia\Database\Document; use Appwrite\Messaging\Adapter; use Utopia\App; +use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -39,20 +39,20 @@ class Realtime extends Adapter /** * Adds a subscription. * - * @param string $projectId - * @param mixed $identifier - * @param array $roles - * @param array $channels + * @param string $projectId + * @param mixed $identifier + * @param array $roles + * @param array $channels * @return void */ public function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void { - if (!isset($this->subscriptions[$projectId])) { // Init Project + if (! isset($this->subscriptions[$projectId])) { // Init Project $this->subscriptions[$projectId] = []; } foreach ($roles as $role) { - if (!isset($this->subscriptions[$projectId][$role])) { // Add user first connection + if (! isset($this->subscriptions[$projectId][$role])) { // Add user first connection $this->subscriptions[$projectId][$role] = []; } @@ -64,14 +64,14 @@ class Realtime extends Adapter $this->connections[$identifier] = [ 'projectId' => $projectId, 'roles' => $roles, - 'channels' => $channels + 'channels' => $channels, ]; } /** * Removes Subscription. * - * @param mixed $connection + * @param mixed $connection * @return void */ public function unsubscribe(mixed $connection): void @@ -102,9 +102,10 @@ class Realtime extends Adapter /** * Checks if Channel has a subscriber. - * @param string $projectId - * @param string $role - * @param string $channel + * + * @param string $projectId + * @param string $role + * @param string $channel * @return bool */ public function hasSubscriber(string $projectId, string $role, string $channel = ''): bool @@ -122,12 +123,13 @@ class Realtime extends Adapter /** * Sends an event to the Realtime Server - * @param string $projectId - * @param array $payload - * @param string $event - * @param array $channels - * @param array $roles - * @param array $options + * + * @param string $projectId + * @param array $payload + * @param string $event + * @param array $channels + * @param array $roles + * @param array $options * @return void */ public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void @@ -150,8 +152,8 @@ class Realtime extends Adapter 'events' => $events, 'channels' => $channels, 'timestamp' => DateTime::formatTz(DateTime::now()), - 'payload' => $payload - ] + 'payload' => $payload, + ], ])); } @@ -166,11 +168,10 @@ class Realtime extends Adapter * - 110.201 ms (±2.32%) | 100,000 Connections / 1,000,000 Subscriptions * - 1,121.328 ms (±0.84%) | 1,000,000 Connections / 10,000,000 Subscriptions * - * @param array $event + * @param array $event */ public function getSubscribers(array $event) { - $receivers = []; /** * Check if project has subscriber. @@ -212,8 +213,9 @@ class Realtime extends Adapter /** * Converts the channels from the Query Params into an array. * Also renames the account channel to account.USER_ID and removes all illegal account channel variations. - * @param array $channels - * @param string $userId + * + * @param array $channels + * @param string $userId * @return array */ public static function convertChannels(array $channels, string $userId): array @@ -227,8 +229,8 @@ class Realtime extends Adapter break; case $key === 'account': - if (!empty($userId)) { - $channels['account.' . $userId] = $value; + if (! empty($userId)) { + $channels['account.'.$userId] = $value; } break; } @@ -240,9 +242,9 @@ class Realtime extends Adapter /** * Create channels array based on the event name and payload. * - * @param string $event - * @param Document $payload - * @param Document|null $project + * @param string $event + * @param Document $payload + * @param Document|null $project * @return array */ public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array @@ -257,18 +259,18 @@ class Realtime extends Adapter switch ($parts[0]) { case 'users': $channels[] = 'account'; - $channels[] = 'account.' . $parts[1]; + $channels[] = 'account.'.$parts[1]; $roles = [Role::user(ID::custom($parts[1]))->toString()]; break; case 'teams': if ($parts[2] === 'memberships') { $permissionsChanged = $parts[4] ?? false; $channels[] = 'memberships'; - $channels[] = 'memberships.' . $parts[3]; + $channels[] = 'memberships.'.$parts[3]; } else { $permissionsChanged = $parts[2] === 'create'; $channels[] = 'teams'; - $channels[] = 'teams.' . $parts[1]; + $channels[] = 'teams.'.$parts[1]; } $roles = [Role::team(ID::custom($parts[1]))->toString()]; break; @@ -286,8 +288,8 @@ class Realtime extends Adapter } $channels[] = 'documents'; - $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents'; - $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId(); + $channels[] = 'databases.'.$database->getId().'.collections.'.$payload->getAttribute('$collectionId').'.documents'; + $channels[] = 'databases.'.$database->getId().'.collections.'.$payload->getAttribute('$collectionId').'.documents.'.$payload->getId(); $roles = $collection->getAttribute('documentSecurity', false) ? \array_merge($collection->getRead(), $payload->getRead()) @@ -300,8 +302,8 @@ class Realtime extends Adapter throw new \Exception('Bucket needs to be passed to Realtime for File events in the Storage.'); } $channels[] = 'files'; - $channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files'; - $channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files.' . $payload->getId(); + $channels[] = 'buckets.'.$payload->getAttribute('bucketId').'.files'; + $channels[] = 'buckets.'.$payload->getAttribute('bucketId').'.files.'.$payload->getId(); $roles = $bucket->getAttribute('fileSecurity', false) ? \array_merge($bucket->getRead(), $payload->getRead()) @@ -312,11 +314,11 @@ class Realtime extends Adapter case 'functions': if ($parts[2] === 'executions') { - if (!empty($payload->getRead())) { + if (! empty($payload->getRead())) { $channels[] = 'console'; $channels[] = 'executions'; - $channels[] = 'executions.' . $payload->getId(); - $channels[] = 'functions.' . $payload->getAttribute('functionId'); + $channels[] = 'executions.'.$payload->getId(); + $channels[] = 'functions.'.$payload->getAttribute('functionId'); $roles = $payload->getRead(); } } elseif ($parts[2] === 'deployments') { @@ -332,7 +334,7 @@ class Realtime extends Adapter 'channels' => $channels, 'roles' => $roles, 'permissionsChanged' => $permissionsChanged, - 'projectId' => $projectId + 'projectId' => $projectId, ]; } } diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 9ea3443091..2685d81829 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -2,15 +2,15 @@ namespace Appwrite\Migration; +use Exception; use Swoole\Runtime; -use Utopia\Database\Document; -use Utopia\Database\Database; -use Utopia\Database\Query; +use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; -use Exception; -use Utopia\App; +use Utopia\Database\Database; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; Runtime::enableCoroutine(SWOOLE_HOOK_ALL); @@ -80,26 +80,25 @@ abstract class Migration $this->collections = array_merge([ '_metadata' => [ '$id' => ID::custom('_metadata'), - '$collection' => Database::METADATA + '$collection' => Database::METADATA, ], 'audit' => [ '$id' => ID::custom('audit'), - '$collection' => Database::METADATA + '$collection' => Database::METADATA, ], 'abuse' => [ '$id' => ID::custom('abuse'), - '$collection' => Database::METADATA - ] + '$collection' => Database::METADATA, + ], ], Config::getParam('collections', [])); } /** * Set project for migration. * - * @param Document $project - * @param Database $projectDB - * @param Database $oldConsoleDB - * + * @param Document $project + * @param Database $projectDB + * @param Database $oldConsoleDB * @return self */ public function setProject(Document $project, Database $projectDB, Database $consoleDB): self @@ -114,7 +113,7 @@ abstract class Migration /** * Set PDO for Migration. * - * @param \PDO $pdo + * @param \PDO $pdo * @return \Appwrite\Migration\Migration */ public function setPDO(\PDO $pdo): self @@ -127,7 +126,7 @@ abstract class Migration /** * Iterates through every document. * - * @param callable $callback + * @param callable $callback */ public function forEachDocument(callable $callback): void { @@ -136,7 +135,7 @@ abstract class Migration continue; } - Console::log('Migrating Collection ' . $collection['$id'] . ':'); + Console::log('Migrating Collection '.$collection['$id'].':'); \Co\run(function (array $collection, callable $callback) { foreach ($this->documentsIterator($collection['$id']) as $document) { @@ -148,14 +147,15 @@ abstract class Migration $old = $document->getArrayCopy(); $new = call_user_func($callback, $document); - if (is_null($new) || !self::hasDifference($new->getArrayCopy(), $old)) { + if (is_null($new) || ! self::hasDifference($new->getArrayCopy(), $old)) { return; } try { $new = $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); } catch (\Throwable $th) { - Console::error('Failed to update document: ' . $th->getMessage()); + Console::error('Failed to update document: '.$th->getMessage()); + return; } }, $document, $callback); @@ -167,8 +167,9 @@ abstract class Migration /** * Provides an iterator for all documents on a collection. * - * @param string $collectionId + * @param string $collectionId * @return iterable + * * @throws \Exception */ public function documentsIterator(string $collectionId): iterable @@ -186,7 +187,7 @@ abstract class Migration $count = count($documents); $sum += $count; - Console::log($sum . ' / ' . $collectionCount); + Console::log($sum.' / '.$collectionCount); foreach ($documents as $document) { yield $document; } @@ -196,28 +197,28 @@ abstract class Migration } else { $nextDocument = end($documents); } - } while (!is_null($nextDocument)); + } while (! is_null($nextDocument)); } /** * Checks 2 arrays for differences. * - * @param array $array1 - * @param array $array2 + * @param array $array1 + * @param array $array2 * @return bool */ public static function hasDifference(array $array1, array $array2): bool { foreach ($array1 as $key => $value) { if (is_array($value)) { - if (!isset($array2[$key]) || !is_array($array2[$key])) { + if (! isset($array2[$key]) || ! is_array($array2[$key])) { return true; } else { if (self::hasDifference($value, $array2[$key])) { return true; } } - } elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) { + } elseif (! array_key_exists($key, $array2) || $array2[$key] !== $value) { return true; } } @@ -228,16 +229,17 @@ abstract class Migration /** * Creates colletion from the config collection. * - * @param string $id - * @param string|null $name + * @param string $id + * @param string|null $name * @return void + * * @throws \Throwable */ protected function createCollection(string $id, string $name = null): void { $name ??= $id; - if (!$this->projectDB->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { + if (! $this->projectDB->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { $attributes = []; $indexes = []; $collection = $this->collections[$id]; @@ -275,10 +277,11 @@ abstract class Migration /** * Creates attribute from collections.php * - * @param \Utopia\Database\Database $database - * @param string $collectionId - * @param string $attributeId + * @param \Utopia\Database\Database $database + * @param string $collectionId + * @param string $attributeId * @return void + * * @throws \Exception * @throws \Utopia\Database\Exception\Duplicate * @throws \Utopia\Database\Exception\Limit @@ -320,11 +323,12 @@ abstract class Migration /** * Creates index from collections.php * - * @param \Utopia\Database\Database $database - * @param string $collectionId - * @param string $indexId - * @param string|null $from + * @param \Utopia\Database\Database $database + * @param string $collectionId + * @param string $indexId + * @param string|null $from * @return void + * * @throws \Exception * @throws \Utopia\Database\Exception\Duplicate * @throws \Utopia\Database\Exception\Limit @@ -360,9 +364,9 @@ abstract class Migration /** * Change a collection attribute's internal type * - * @param string $collection - * @param string $attribute - * @param string $type + * @param string $collection + * @param string $attribute + * @param string $type * @return void */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index b6deb780da..dadf971675 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -4,8 +4,6 @@ namespace Appwrite\Migration\Version; use Appwrite\Migration\Migration; use Appwrite\OpenSSL\OpenSSL; -use Exception; -use PDO; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -33,7 +31,7 @@ class V15 extends Migration $this->providers = \array_merge( ['email', 'anonymous'], \array_map( - fn ($value) => "oauth-" . $value, + fn ($value) => 'oauth-'.$value, \array_keys(Config::getParam('authProviders', [])) ) ); @@ -49,7 +47,7 @@ class V15 extends Migration ); } - Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); Console::info('Migrating Stats'); $this->migrateStatsMetric('requests', 'project.$all.network.requests'); $this->migrateStatsMetric('network', 'project.$all.network.bandwidth'); @@ -76,6 +74,7 @@ class V15 extends Migration * Migrating all Bucket tables. * * @return void + * * @throws \Exception * @throws \PDOException */ @@ -108,7 +107,7 @@ class V15 extends Migration addCreatePermission: true ); - if (!is_null($bucket->getAttribute('permission'))) { + if (! is_null($bucket->getAttribute('permission'))) { $bucket->setAttribute('fileSecurity', $bucket->getAttribute('permissions') === 'document'); } @@ -152,6 +151,7 @@ class V15 extends Migration * Migrating all Database and Collection tables. * * @return void + * * @throws \Exception * @throws \PDOException */ @@ -229,7 +229,7 @@ class V15 extends Migration addCreatePermission: true ); - if (!is_null($collection->getAttribute('permission'))) { + if (! is_null($collection->getAttribute('permission'))) { $collection->setAttribute('documentSecurity', $collection->getAttribute('permissions') === 'document'); } @@ -249,9 +249,10 @@ class V15 extends Migration $requiredAttributes = array_reduce($collection->getAttribute('attributes', []), function (array $carry, Document $item) { if ($item->getAttribute('required', false)) { $carry = array_merge($carry, [ - $item->getAttribute('key') => $item->getAttribute('default') + $item->getAttribute('key') => $item->getAttribute('default'), ]); } + return $carry; }, []); @@ -289,7 +290,7 @@ class V15 extends Migration /** * Removes all 'write' permissions from a table. * - * @param string $table + * @param string $table * @return void */ protected function removeWritePermissions(string $table): void @@ -304,8 +305,9 @@ class V15 extends Migration /** * Returns all columns from the Table. * - * @param string $table + * @param string $table * @return array + * * @throws \Exception * @throws \PDOException */ @@ -325,6 +327,7 @@ class V15 extends Migration * Migrates all Integer colums for timestamps to DateTime. * * @return void + * * @throws \Exception */ protected function migrateDateTimeAttribute(string $table, string $attribute): void @@ -352,7 +355,7 @@ class V15 extends Migration /** * Skip adding filter on internal attributes. */ - if (!str_starts_with($attribute, '_')) { + if (! str_starts_with($attribute, '_')) { try { /** * Add datetime filter. @@ -378,8 +381,9 @@ class V15 extends Migration /** * Create the '_permissions' column to a table. * - * @param string $table + * @param string $table * @return void + * * @throws \Exception * @throws \PDOException */ @@ -387,7 +391,7 @@ class V15 extends Migration { $columns = $this->getSQLColumnTypes($table); - if (!array_key_exists('_permissions', $columns)) { + if (! array_key_exists('_permissions', $columns)) { try { $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { @@ -399,10 +403,11 @@ class V15 extends Migration /** * Populate '$permissions' from '$read' and '$write'. * - * @param \Utopia\Database\Document $document - * @param null|string $table - * @param bool $addCreatePermission + * @param \Utopia\Database\Document $document + * @param null|string $table + * @param bool $addCreatePermission * @return void + * * @throws \Exception * @throws \PDOException */ @@ -443,7 +448,7 @@ class V15 extends Migration /** * Migrates a permission string * - * @param string $permission + * @param string $permission * @return string */ protected function migratePermission(string $permission): string @@ -730,7 +735,7 @@ class V15 extends Migration foreach ($this->documentsIterator($id) as $function) { $vars = $function->getAttribute('vars', []); - if (!is_array($vars)) { + if (! is_array($vars)) { continue; } @@ -751,7 +756,7 @@ class V15 extends Migration 'functionInternalId' => $function->getInternalId(), 'key' => (string) $key, 'value' => (string) $value, - 'search' => implode(' ', [$variableId, $key, $function->getId()]) + 'search' => implode(' ', [$variableId, $key, $function->getId()]), ]); $this->projectDB->createDocument('variables', $variable); } @@ -1223,7 +1228,7 @@ class V15 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) @@ -1474,14 +1479,14 @@ class V15 extends Migration $this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); + Console::warning("Migrating steps from {$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats:".$th->getMessage()); } } /** * Filter from the 'encrypt' filter. * - * @param string $value + * @param string $value * @return string|false */ protected function encryptFilter(string $value): string diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index bee2236dfb..761a274e0f 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -24,7 +24,7 @@ class V16 extends Migration ); } - Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -102,7 +102,7 @@ class V16 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) @@ -118,7 +118,7 @@ class V16 extends Migration * Set default authDuration */ $document->setAttribute('auths', array_merge($document->getAttribute('auths', []), [ - 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG + 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, ])); /** @@ -127,16 +127,16 @@ class V16 extends Migration $authProviders = $document->getAttribute('authProviders', []); foreach (Config::getParam('authProviders') as $provider => $value) { - if (!$value['enabled']) { + if (! $value['enabled']) { continue; } - if (($authProviders[$provider . 'Appid'] ?? false) && ($authProviders[$provider . 'Secret'] ?? false)) { - if (array_key_exists($provider . 'Enabled', $authProviders)) { + if (($authProviders[$provider.'Appid'] ?? false) && ($authProviders[$provider.'Secret'] ?? false)) { + if (array_key_exists($provider.'Enabled', $authProviders)) { continue; } - $authProviders[$provider . 'Enabled'] = true; + $authProviders[$provider.'Enabled'] = true; } } diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index 3f744d8069..421c86bcc8 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -23,7 +23,7 @@ class V17 extends Migration ); } - Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -33,11 +33,11 @@ class V17 extends Migration $this->forEachDocument([$this, 'fixDocument']); } - /** * Migrating all Bucket tables. * * @return void + * * @throws \Exception * @throws \PDOException */ @@ -234,7 +234,7 @@ class V17 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) @@ -250,15 +250,15 @@ class V17 extends Migration * Set default maxSessions */ $document->setAttribute('auths', array_merge($document->getAttribute('auths', []), [ - 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT + 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT, ])); break; case 'users': - /** + /** * Set hashOptions type */ $document->setAttribute('hashOptions', array_merge($document->getAttribute('hashOptions', []), [ - 'type' => $document->getAttribute('hash', Auth::DEFAULT_ALGO) + 'type' => $document->getAttribute('hash', Auth::DEFAULT_ALGO), ])); break; } diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index 839269f940..2b3b98088d 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -13,7 +13,6 @@ class V18 extends Migration { public function execute(): void { - /** * Disable SubQueries for Performance. */ @@ -25,7 +24,7 @@ class V18 extends Migration ); } - Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); $this->addDocumentSecurityToProject(); @@ -43,6 +42,7 @@ class V18 extends Migration * Migrate all Databases. * * @return void + * * @throws \Exception */ private function migrateDatabases(): void @@ -154,7 +154,7 @@ class V18 extends Migration /** * Fix run on each document * - * @param Document $document + * @param Document $document * @return Document */ protected function fixDocument(Document $document): Document diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index 39522aff0b..fe9bde6d29 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -2,8 +2,6 @@ namespace Appwrite\Migration\Version; -use Appwrite\Auth\Auth; -use Utopia\Config\Config; use Appwrite\Migration\Migration; use Utopia\CLI\Console; use Utopia\Database\Database; @@ -13,7 +11,6 @@ class V19 extends Migration { public function execute(): void { - /** * Disable SubQueries for Performance. */ @@ -25,7 +22,7 @@ class V19 extends Migration ); } - Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); $this->alterPermissionIndex('_metadata'); @@ -48,6 +45,7 @@ class V19 extends Migration * Migrate all Databases. * * @return void + * * @throws \Exception */ private function migrateDatabases(): void @@ -99,7 +97,7 @@ class V19 extends Migration default: break; } - if (!in_array($id, ['files', 'collections'])) { + if (! in_array($id, ['files', 'collections'])) { $this->alterPermissionIndex($id); $this->alterUidType($id); } @@ -111,7 +109,7 @@ class V19 extends Migration /** * Fix run on each document * - * @param Document $document + * @param Document $document * @return Document */ protected function fixDocument(Document $document): Document @@ -163,6 +161,7 @@ class V19 extends Migration * Migrating all Bucket tables. * * @return void + * * @throws \Exception * @throws \PDOException */ diff --git a/src/Appwrite/Network/Validator/CNAME.php b/src/Appwrite/Network/Validator/CNAME.php index 678a57cecd..3840322137 100644 --- a/src/Appwrite/Network/Validator/CNAME.php +++ b/src/Appwrite/Network/Validator/CNAME.php @@ -12,7 +12,7 @@ class CNAME extends Validator protected $target; /** - * @param string $target + * @param string $target */ public function __construct($target) { @@ -30,13 +30,12 @@ class CNAME extends Validator /** * Check if CNAME record target value matches selected target * - * @param mixed $domain - * + * @param mixed $domain * @return bool */ public function isValid($domain): bool { - if (!is_string($domain)) { + if (! is_string($domain)) { return false; } @@ -46,7 +45,7 @@ class CNAME extends Validator return false; } - if (!$records) { + if (! $records) { return false; } diff --git a/src/Appwrite/Network/Validator/Email.php b/src/Appwrite/Network/Validator/Email.php index efc1a5d5b3..232437aab7 100644 --- a/src/Appwrite/Network/Validator/Email.php +++ b/src/Appwrite/Network/Validator/Email.php @@ -8,8 +8,6 @@ use Utopia\Validator; * Email * * Validate that an variable is a valid email address - * - * @package Utopia\Validator */ class Email extends Validator { @@ -30,12 +28,12 @@ class Email extends Validator * * Validation will pass when $value is valid email address. * - * @param mixed $value + * @param mixed $value * @return bool */ public function isValid($value): bool { - if (!\filter_var($value, FILTER_VALIDATE_EMAIL)) { + if (! \filter_var($value, FILTER_VALIDATE_EMAIL)) { return false; } diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 508961ab9e..78065c0e48 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -2,35 +2,55 @@ namespace Appwrite\Network\Validator; -use Utopia\Validator\Hostname; use Utopia\Validator; +use Utopia\Validator\Hostname; class Origin extends Validator { public const CLIENT_TYPE_UNKNOWN = 'unknown'; + public const CLIENT_TYPE_WEB = 'web'; + public const CLIENT_TYPE_FLUTTER_IOS = 'flutter-ios'; + public const CLIENT_TYPE_FLUTTER_ANDROID = 'flutter-android'; + public const CLIENT_TYPE_FLUTTER_MACOS = 'flutter-macos'; + public const CLIENT_TYPE_FLUTTER_WINDOWS = 'flutter-windows'; + public const CLIENT_TYPE_FLUTTER_LINUX = 'flutter-linux'; + public const CLIENT_TYPE_FLUTTER_WEB = 'flutter-web'; + public const CLIENT_TYPE_APPLE_IOS = 'apple-ios'; + public const CLIENT_TYPE_APPLE_MACOS = 'apple-macos'; + public const CLIENT_TYPE_APPLE_WATCHOS = 'apple-watchos'; + public const CLIENT_TYPE_APPLE_TVOS = 'apple-tvos'; + public const CLIENT_TYPE_ANDROID = 'android'; + public const CLIENT_TYPE_UNITY = 'unity'; - public const SCHEME_TYPE_HTTP = 'http'; + public const SCHEME_TYPE_HTTPS = 'https'; + public const SCHEME_TYPE_IOS = 'appwrite-ios'; + public const SCHEME_TYPE_MACOS = 'appwrite-macos'; + public const SCHEME_TYPE_WATCHOS = 'appwrite-watchos'; + public const SCHEME_TYPE_TVOS = 'appwrite-tvos'; + public const SCHEME_TYPE_ANDROID = 'appwrite-android'; + public const SCHEME_TYPE_WINDOWS = 'appwrite-windows'; + public const SCHEME_TYPE_LINUX = 'appwrite-linux'; /** @@ -65,7 +85,7 @@ class Origin extends Validator protected $host = ''; /** - * @param string $target + * @param string $target */ public function __construct($platforms) { @@ -92,7 +112,7 @@ class Origin extends Validator break; default: - # code... + // code... break; } } @@ -100,25 +120,24 @@ class Origin extends Validator public function getDescription(): string { - if (!\array_key_exists($this->client, $this->platforms)) { + if (! \array_key_exists($this->client, $this->platforms)) { return 'Unsupported platform'; } - return 'Invalid Origin. Register your new client (' . $this->host . ') as a new ' - . $this->platforms[$this->client] . ' platform on your project console dashboard'; + return 'Invalid Origin. Register your new client ('.$this->host.') as a new ' + .$this->platforms[$this->client].' platform on your project console dashboard'; } /** * Check if Origin has been allowed * for access to the API * - * @param mixed $origin - * + * @param mixed $origin * @return bool */ public function isValid($origin): bool { - if (!is_string($origin)) { + if (! is_string($origin)) { return false; } diff --git a/src/Appwrite/OpenSSL/OpenSSL.php b/src/Appwrite/OpenSSL/OpenSSL.php index 1965a3c858..2eed67dd3e 100644 --- a/src/Appwrite/OpenSSL/OpenSSL.php +++ b/src/Appwrite/OpenSSL/OpenSSL.php @@ -10,12 +10,11 @@ class OpenSSL * @param $data * @param $method * @param $key - * @param int $options - * @param string $iv - * @param null $tag - * @param string $aad - * @param int $tag_length - * + * @param int $options + * @param string $iv + * @param null $tag + * @param string $aad + * @param int $tag_length * @return string */ public static function encrypt($data, $method, $key, $options = 0, $iv = '', &$tag = null, $aad = '', $tag_length = 16) @@ -27,11 +26,10 @@ class OpenSSL * @param $data * @param $method * @param $password - * @param int $options - * @param string $iv - * @param string $tag - * @param string $aad - * + * @param int $options + * @param string $iv + * @param string $tag + * @param string $aad * @return string */ public static function decrypt($data, $method, $password, $options = 1, $iv = '', $tag = '', $aad = '') @@ -40,8 +38,7 @@ class OpenSSL } /** - * @param string $method - * + * @param string $method * @return int */ public static function cipherIVLength($method) @@ -51,8 +48,7 @@ class OpenSSL /** * @param $length - * @param null $crypto_strong - * + * @param null $crypto_strong * @return false|string */ public static function randomPseudoBytes($length, &$crypto_strong = null) diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index 9e919127bf..a24d72be2f 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -2,26 +2,25 @@ namespace Appwrite\Platform\Services; -use Utopia\Platform\Service; +use Appwrite\Platform\Tasks\CalcTierStats; +use Appwrite\Platform\Tasks\CalcUsersStats; +use Appwrite\Platform\Tasks\ClearCardCache; use Appwrite\Platform\Tasks\Doctor; +use Appwrite\Platform\Tasks\Hamster; use Appwrite\Platform\Tasks\Install; use Appwrite\Platform\Tasks\Maintenance; use Appwrite\Platform\Tasks\Migrate; -use Appwrite\Platform\Tasks\Schedule; use Appwrite\Platform\Tasks\PatchCreateMissingSchedules; +use Appwrite\Platform\Tasks\PatchDeleteProjectCollections; +use Appwrite\Platform\Tasks\PatchDeleteScheduleUpdatedAtAttribute; +use Appwrite\Platform\Tasks\Schedule; use Appwrite\Platform\Tasks\SDKs; use Appwrite\Platform\Tasks\Specs; use Appwrite\Platform\Tasks\SSL; -use Appwrite\Platform\Tasks\Hamster; -use Appwrite\Platform\Tasks\PatchDeleteScheduleUpdatedAtAttribute; -use Appwrite\Platform\Tasks\ClearCardCache; -use Appwrite\Platform\Tasks\Usage; use Appwrite\Platform\Tasks\Vars; use Appwrite\Platform\Tasks\Version; use Appwrite\Platform\Tasks\VolumeSync; -use Appwrite\Platform\Tasks\CalcUsersStats; -use Appwrite\Platform\Tasks\CalcTierStats; -use Appwrite\Platform\Tasks\PatchDeleteProjectCollections; +use Utopia\Platform\Service; class Tasks extends Service { @@ -46,7 +45,6 @@ class Tasks extends Service ->addAction(Specs::getName(), new Specs()) ->addAction(CalcUsersStats::getName(), new CalcUsersStats()) ->addAction(CalcTierStats::getName(), new CalcTierStats()) - ->addAction(PatchDeleteProjectCollections::getName(), new PatchDeleteProjectCollections()) - ; + ->addAction(PatchDeleteProjectCollections::getName(), new PatchDeleteProjectCollections()); } } diff --git a/src/Appwrite/Platform/Tasks/CalcTierStats.php b/src/Appwrite/Platform/Tasks/CalcTierStats.php index d660709940..0dc795cbcd 100644 --- a/src/Appwrite/Platform/Tasks/CalcTierStats.php +++ b/src/Appwrite/Platform/Tasks/CalcTierStats.php @@ -4,15 +4,15 @@ namespace Appwrite\Platform\Tasks; use Exception; use League\Csv\CannotInsertRecord; +use League\Csv\Writer; +use PHPMailer\PHPMailer\PHPMailer; use Utopia\App; -use Utopia\Database\Validator\Authorization; -use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Query; -use League\Csv\Writer; -use PHPMailer\PHPMailer\PHPMailer; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -44,11 +44,13 @@ class CalcTierStats extends Action ]; protected string $directory = '/usr/local'; + protected string $path; + protected string $date; private array $usageStats = [ - 'project.$all.network.requests' => 'Requests', + 'project.$all.network.requests' => 'Requests', 'project.$all.network.bandwidth' => 'Bandwidth', ]; @@ -60,7 +62,6 @@ class CalcTierStats extends Action public function __construct() { - $this ->desc('Get stats for projects') ->inject('pools') @@ -81,7 +82,7 @@ class CalcTierStats extends Action //docker compose exec -t appwrite calc-tier-stats Console::title('Cloud free tier stats calculation V1'); - Console::success(APP_NAME . ' cloud free tier stats calculation has started'); + Console::success(APP_NAME.' cloud free tier stats calculation has started'); /* Initialise new Utopia app */ $app = new App('UTC'); @@ -102,9 +103,8 @@ class CalcTierStats extends Action $limit = 30; $sum = 30; $offset = 0; - while (!empty($projects)) { + while (! empty($projects)) { foreach ($projects as $project) { - /** * Skip user projects with id 'console' */ @@ -123,18 +123,18 @@ class CalcTierStats extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase('appwrite'); - $dbForProject->setNamespace('_' . $project->getInternalId()); + $dbForProject->setNamespace('_'.$project->getInternalId()); /** Get Project ID */ $stats['Project ID'] = $project->getId(); - $stats['Organization ID'] = $project->getAttribute('teamId', null); + $stats['Organization ID'] = $project->getAttribute('teamId', null); /** Get Total Members */ $teamInternalId = $project->getAttribute('teamInternalId', null); if ($teamInternalId) { $stats['Organization Members'] = $dbForConsole->count('memberships', [ - Query::equal('teamInternalId', [$teamInternalId]) + Query::equal('teamInternalId', [$teamInternalId]), ]); } else { $stats['Organization Members'] = 0; @@ -195,7 +195,7 @@ class CalcTierStats extends Action }); foreach ($tmp as $key => $value) { - $stats[$metrics[$key]] = $value; + $stats[$metrics[$key]] = $value; } try { @@ -208,27 +208,27 @@ class CalcTierStats extends Action } try { - /** Get Api keys */ + /** Get Api keys */ $stats['Api keys'] = $dbForConsole->count('keys', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); } catch (\Throwable) { $stats['Api keys'] = 0; } try { - /** Get Webhooks */ + /** Get Webhooks */ $stats['Webhooks'] = $dbForConsole->count('webhooks', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); } catch (\Throwable) { $stats['Webhooks'] = 0; } try { - /** Get Platforms */ + /** Get Platforms */ $stats['Platforms'] = $dbForConsole->count('platforms', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); } catch (\Throwable) { $stats['Platforms'] = 0; @@ -242,28 +242,26 @@ class CalcTierStats extends Action try { $buckets = $dbForProject->find('buckets', []); foreach ($buckets as $bucket) { - $file = $dbForProject->findOne('bucket_' . $bucket->getInternalId(), [Query::orderDesc('sizeOriginal'),]); + $file = $dbForProject->findOne('bucket_'.$bucket->getInternalId(), [Query::orderDesc('sizeOriginal')]); if (empty($file)) { continue; } - $filesSum += $dbForProject->sum('bucket_' . $bucket->getInternalId(), 'sizeOriginal', [], 0); - $filesCount += $dbForProject->count('bucket_' . $bucket->getInternalId(), []); + $filesSum += $dbForProject->sum('bucket_'.$bucket->getInternalId(), 'sizeOriginal', [], 0); + $filesCount += $dbForProject->count('bucket_'.$bucket->getInternalId(), []); if ($file->getAttribute('sizeOriginal') > $maxFileSize) { $maxFileSize = $file->getAttribute('sizeOriginal'); } $counter++; } } catch (\Throwable) { - ; } $stats['Buckets'] = $counter; $stats['Files'] = $filesCount; $stats['Storage (bytes)'] = $filesSum; $stats['Max File Size (bytes)'] = $maxFileSize; - try { - /** Get Total Functions */ + /** Get Total Functions */ $stats['Databases'] = $dbForProject->count('databases', []); } catch (\Throwable) { $stats['Databases'] = 0; @@ -292,7 +290,7 @@ class CalcTierStats extends Action $csv->insertOne(array_values($stats)); } catch (\Throwable $th) { - Console::error('Failed on project ("' . $project->getId() . '") version with error on File: ' . $th->getFile() . ' line no: ' . $th->getline() . ' with message: ' . $th->getMessage()); + Console::error('Failed on project ("'.$project->getId().'") version with error on File: '.$th->getFile().' line no: '.$th->getline().' with message: '.$th->getMessage()); } finally { $pools ->get($db) @@ -311,7 +309,7 @@ class CalcTierStats extends Action $count = $count + $sum; } - Console::log('Iterated through ' . $count - 1 . '/' . $totalProjects . ' projects...'); + Console::log('Iterated through '.$count - 1 .'/'.$totalProjects.' projects...'); $pools ->get('console') @@ -341,7 +339,7 @@ class CalcTierStats extends Action /** Content */ $mail->Subject = "Cloud Report for {$this->date}"; - $mail->Body = "Please find the daily cloud report atttached"; + $mail->Body = 'Please find the daily cloud report atttached'; $mail->send(); Console::success('Email has been sent!'); } catch (Exception $e) { diff --git a/src/Appwrite/Platform/Tasks/CalcUsersStats.php b/src/Appwrite/Platform/Tasks/CalcUsersStats.php index 6310fe17b4..67fcc1a5c5 100644 --- a/src/Appwrite/Platform/Tasks/CalcUsersStats.php +++ b/src/Appwrite/Platform/Tasks/CalcUsersStats.php @@ -3,14 +3,14 @@ namespace Appwrite\Platform\Tasks; use Exception; +use League\Csv\Writer; +use PHPMailer\PHPMailer\PHPMailer; use Utopia\App; -use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Query; -use League\Csv\Writer; -use PHPMailer\PHPMailer\PHPMailer; +use Utopia\Platform\Action; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -21,11 +21,13 @@ class CalcUsersStats extends Action 'Project Name', 'Team ID', 'Team name', - 'Users' + 'Users', ]; protected string $directory = '/usr/local'; + protected string $path; + protected string $date; public static function getName(): string @@ -35,7 +37,6 @@ class CalcUsersStats extends Action public function __construct() { - $this ->desc('Get stats for projects') ->inject('pools') @@ -52,7 +53,7 @@ class CalcUsersStats extends Action //docker compose exec -t appwrite calc-users-stats Console::title('Cloud Users calculation V1'); - Console::success(APP_NAME . ' cloud Users calculation has started'); + Console::success(APP_NAME.' cloud Users calculation has started'); /* Initialise new Utopia app */ $app = new App('UTC'); @@ -73,9 +74,8 @@ class CalcUsersStats extends Action $limit = 30; $sum = 30; $offset = 0; - while (!empty($projects)) { + while (! empty($projects)) { foreach ($projects as $project) { - /** * Skip user projects with id 'console' */ @@ -94,7 +94,7 @@ class CalcUsersStats extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase('appwrite'); - $dbForProject->setNamespace('_' . $project->getInternalId()); + $dbForProject->setNamespace('_'.$project->getInternalId()); /** Get Project ID */ $stats['Project ID'] = $project->getId(); @@ -102,7 +102,6 @@ class CalcUsersStats extends Action /** Get Project Name */ $stats['Project Name'] = $project->getAttribute('name'); - /** Get Team Name and Id */ $teamId = $project->getAttribute('teamId', null); $teamName = null; @@ -111,7 +110,7 @@ class CalcUsersStats extends Action $teamName = $team->getAttribute('name'); } - $stats['Team ID'] = $teamId; + $stats['Team ID'] = $teamId; $stats['Team name'] = $teamName; /** Get Total Users */ @@ -119,7 +118,7 @@ class CalcUsersStats extends Action $csv->insertOne(array_values($stats)); } catch (\Throwable $th) { - Console::error('Failed to update project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); + Console::error('Failed to update project ("'.$project->getId().'") version with error: '.$th->getMessage()); } finally { $pools ->get($db) @@ -137,7 +136,7 @@ class CalcUsersStats extends Action $offset = $offset + $limit; $count = $count + $sum; } - Console::log('Iterated through ' . $count - 1 . '/' . $totalProjects . ' projects...'); + Console::log('Iterated through '.$count - 1 .'/'.$totalProjects.' projects...'); $pools ->get('console') ->reclaim(); @@ -166,7 +165,7 @@ class CalcUsersStats extends Action /** Content */ $mail->Subject = "Cloud Report for {$this->date}"; - $mail->Body = "Please find the daily cloud report atttached"; + $mail->Body = 'Please find the daily cloud report atttached'; $mail->send(); Console::success('Email has been sent!'); } catch (Exception $e) { diff --git a/src/Appwrite/Platform/Tasks/ClearCardCache.php b/src/Appwrite/Platform/Tasks/ClearCardCache.php index d3153b995c..59499b6888 100644 --- a/src/Appwrite/Platform/Tasks/ClearCardCache.php +++ b/src/Appwrite/Platform/Tasks/ClearCardCache.php @@ -4,12 +4,12 @@ namespace Appwrite\Platform\Tasks; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; -use Utopia\Platform\Action; use Utopia\CLI\Console; -use Utopia\Database\Query; use Utopia\Database\Database; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; class ClearCardCache extends Action { @@ -33,12 +33,12 @@ class ClearCardCache extends Action Authorization::setDefaultStatus(false); Console::title('ClearCardCache V1'); - Console::success(APP_NAME . ' ClearCardCache v1 has started'); - $resources = ['card/' . $userId, 'card-back/' . $userId, 'card-og/' . $userId]; + Console::success(APP_NAME.' ClearCardCache v1 has started'); + $resources = ['card/'.$userId, 'card-back/'.$userId, 'card-og/'.$userId]; $caches = Authorization::skip(fn () => $dbForConsole->find('cache', [ Query::equal('resource', $resources), - Query::limit(100) + Query::limit(100), ])); $count = \count($caches); @@ -49,7 +49,7 @@ class ClearCardCache extends Action $key = $cache->getId(); $cacheFolder = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-console') + new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-console') ); $cacheFolder->purge($key); @@ -57,6 +57,6 @@ class ClearCardCache extends Action Authorization::skip(fn () => $dbForConsole->deleteDocument('cache', $cache->getId())); } - Console::success(APP_NAME . ' ClearCardCache v1 has finished'); + Console::success(APP_NAME.' ClearCardCache v1 has finished'); } } diff --git a/src/Appwrite/Platform/Tasks/Doctor.php b/src/Appwrite/Platform/Tasks/Doctor.php index 9a6d6a2847..8b37e578f4 100644 --- a/src/Appwrite/Platform/Tasks/Doctor.php +++ b/src/Appwrite/Platform/Tasks/Doctor.php @@ -2,16 +2,16 @@ namespace Appwrite\Platform\Tasks; +use Appwrite\ClamAV\Network; use Utopia\App; use Utopia\CLI\Console; -use Appwrite\ClamAV\Network; -use Utopia\Logger\Logger; -use Utopia\Storage\Device\Local; -use Utopia\Storage\Storage; use Utopia\Config\Config; use Utopia\Domains\Domain; +use Utopia\Logger\Logger; use Utopia\Platform\Action; use Utopia\Registry\Registry; +use Utopia\Storage\Device\Local; +use Utopia\Storage\Storage; class Doctor extends Action { @@ -35,24 +35,24 @@ class Doctor extends Action / \ ) __/ ) __/\ /\ / ) / )( )( ) _) _ )(( O ) \_/\_/(__) (__) (_/\_)(__\_)(__) (__) (____)(_)(__)\__/ "); - Console::log("\n" . '👩‍⚕️ Running ' . APP_NAME . ' Doctor for version ' . App::getEnv('_APP_VERSION', 'UNKNOWN') . ' ...' . "\n"); + Console::log("\n".'👩‍⚕️ Running '.APP_NAME.' Doctor for version '.App::getEnv('_APP_VERSION', 'UNKNOWN').' ...'."\n"); Console::log('[Settings]'); $domain = new Domain(App::getEnv('_APP_DOMAIN')); - if (!$domain->isKnown() || $domain->isTest()) { - Console::log('🔴 Hostname has no public suffix (' . $domain->get() . ')'); + if (! $domain->isKnown() || $domain->isTest()) { + Console::log('🔴 Hostname has no public suffix ('.$domain->get().')'); } else { - Console::log('🟢 Hostname has a public suffix (' . $domain->get() . ')'); + Console::log('🟢 Hostname has a public suffix ('.$domain->get().')'); } $domain = new Domain(App::getEnv('_APP_DOMAIN_TARGET')); - if (!$domain->isKnown() || $domain->isTest()) { - Console::log('🔴 CNAME target has no public suffix (' . $domain->get() . ')'); + if (! $domain->isKnown() || $domain->isTest()) { + Console::log('🔴 CNAME target has no public suffix ('.$domain->get().')'); } else { - Console::log('🟢 CNAME target has a public suffix (' . $domain->get() . ')'); + Console::log('🟢 CNAME target has a public suffix ('.$domain->get().')'); } if (App::getEnv('_APP_OPENSSL_KEY_V1') === 'your-secret-key' || empty(App::getEnv('_APP_OPENSSL_KEY_V1'))) { @@ -96,22 +96,21 @@ class Doctor extends Action $providerName = App::getEnv('_APP_LOGGING_PROVIDER', ''); $providerConfig = App::getEnv('_APP_LOGGING_CONFIG', ''); - if (empty($providerName) || empty($providerConfig) || !Logger::hasProvider($providerName)) { + if (empty($providerName) || empty($providerConfig) || ! Logger::hasProvider($providerName)) { Console::log('🔴 Logging adapter is disabled'); } else { - Console::log('🟢 Logging adapter is enabled (' . $providerName . ')'); + Console::log('🟢 Logging adapter is enabled ('.$providerName.')'); } \sleep(0.2); try { - Console::log("\n" . '[Connectivity]'); + Console::log("\n".'[Connectivity]'); } catch (\Throwable $th) { //throw $th; } $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ - $configs = [ 'Console.DB' => Config::getParam('pools-console'), 'Projects.DB' => Config::getParam('pools-database'), @@ -123,12 +122,12 @@ class Doctor extends Action $adapter = $pools->get($database)->pop()->getResource(); if ($adapter->ping()) { - Console::success('🟢 ' . str_pad("{$key}({$database})", 50, '.') . 'connected'); + Console::success('🟢 '.str_pad("{$key}({$database})", 50, '.').'connected'); } else { - Console::error('🔴 ' . str_pad("{$key}({$database})", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad("{$key}({$database})", 47, '.').'disconnected'); } } catch (\Throwable $th) { - Console::error('🔴 ' . str_pad("{$key}.({$database})", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad("{$key}.({$database})", 47, '.').'disconnected'); } } } @@ -146,12 +145,12 @@ class Doctor extends Action $adapter = $pools->get($pool)->pop()->getResource(); if ($adapter->ping()) { - Console::success('🟢 ' . str_pad("{$key}({$pool})", 50, '.') . 'connected'); + Console::success('🟢 '.str_pad("{$key}({$pool})", 50, '.').'connected'); } else { - Console::error('🔴 ' . str_pad("{$key}({$pool})", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad("{$key}({$pool})", 47, '.').'disconnected'); } } catch (\Throwable $th) { - Console::error('🔴 ' . str_pad("{$key}({$pool})", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad("{$key}({$pool})", 47, '.').'disconnected'); } } } @@ -164,12 +163,12 @@ class Doctor extends Action ); if ((@$antivirus->ping())) { - Console::success('🟢 ' . str_pad("Antivirus", 50, '.') . 'connected'); + Console::success('🟢 '.str_pad('Antivirus', 50, '.').'connected'); } else { - Console::error('🔴 ' . str_pad("Antivirus", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad('Antivirus', 47, '.').'disconnected'); } } catch (\Throwable $th) { - Console::error('🔴 ' . str_pad("Antivirus", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad('Antivirus', 47, '.').'disconnected'); } } @@ -182,9 +181,9 @@ class Doctor extends Action $mail->AltBody = 'Hello World'; $mail->send(); - Console::success('🟢 ' . str_pad("SMTP", 50, '.') . 'connected'); + Console::success('🟢 '.str_pad('SMTP', 50, '.').'connected'); } catch (\Throwable $th) { - Console::error('🔴 ' . str_pad("SMTP", 47, '.') . 'disconnected'); + Console::error('🔴 '.str_pad('SMTP', 47, '.').'disconnected'); } \sleep(0.2); @@ -194,24 +193,24 @@ class Doctor extends Action foreach ( [ - 'Uploads' => APP_STORAGE_UPLOADS, - 'Cache' => APP_STORAGE_CACHE, - 'Config' => APP_STORAGE_CONFIG, - 'Certs' => APP_STORAGE_CERTIFICATES + 'Uploads' => APP_STORAGE_UPLOADS, + 'Cache' => APP_STORAGE_CACHE, + 'Config' => APP_STORAGE_CONFIG, + 'Certs' => APP_STORAGE_CERTIFICATES, ] as $key => $volume ) { $device = new Local($volume); if (\is_readable($device->getRoot())) { - Console::success('🟢 ' . $key . ' Volume is readable'); + Console::success('🟢 '.$key.' Volume is readable'); } else { - Console::error('🔴 ' . $key . ' Volume is unreadable'); + Console::error('🔴 '.$key.' Volume is unreadable'); } if (\is_writable($device->getRoot())) { - Console::success('🟢 ' . $key . ' Volume is writeable'); + Console::success('🟢 '.$key.' Volume is writeable'); } else { - Console::error('🔴 ' . $key . ' Volume is unwriteable'); + Console::error('🔴 '.$key.' Volume is unwriteable'); } } @@ -222,10 +221,10 @@ class Doctor extends Action foreach ( [ - 'Uploads' => APP_STORAGE_UPLOADS, - 'Cache' => APP_STORAGE_CACHE, - 'Config' => APP_STORAGE_CONFIG, - 'Certs' => APP_STORAGE_CERTIFICATES + 'Uploads' => APP_STORAGE_UPLOADS, + 'Cache' => APP_STORAGE_CACHE, + 'Config' => APP_STORAGE_CONFIG, + 'Certs' => APP_STORAGE_CERTIFICATES, ] as $key => $volume ) { $device = new Local($volume); @@ -233,32 +232,32 @@ class Doctor extends Action $percentage = (($device->getPartitionTotalSpace() - $device->getPartitionFreeSpace()) / $device->getPartitionTotalSpace()) * 100; - $message = $key . ' Volume has ' . Storage::human($device->getPartitionFreeSpace()) . ' free space (' . \round($percentage, 2) . '% used)'; + $message = $key.' Volume has '.Storage::human($device->getPartitionFreeSpace()).' free space ('.\round($percentage, 2).'% used)'; if ($percentage < 80) { - Console::success('🟢 ' . $message); + Console::success('🟢 '.$message); } else { - Console::error('🔴 ' . $message); + Console::error('🔴 '.$message); } } try { if (App::isProduction()) { Console::log(''); - $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost') . '/v1/health/version'), true); + $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost').'/v1/health/version'), true); if ($version && isset($version['version'])) { if (\version_compare($version['version'], App::getEnv('_APP_VERSION', 'UNKNOWN')) === 0) { - Console::info('You are running the latest version of ' . APP_NAME . '! 🥳'); + Console::info('You are running the latest version of '.APP_NAME.'! 🥳'); } else { - Console::info('A new version (' . $version['version'] . ') is available! 🥳' . "\n"); + Console::info('A new version ('.$version['version'].') is available! 🥳'."\n"); } } else { - Console::error('Failed to check for a newer version' . "\n"); + Console::error('Failed to check for a newer version'."\n"); } } } catch (\Throwable $th) { - Console::error('Failed to check for a newer version' . "\n"); + Console::error('Failed to check for a newer version'."\n"); } } } diff --git a/src/Appwrite/Platform/Tasks/Hamster.php b/src/Appwrite/Platform/Tasks/Hamster.php index 5b04c338eb..85545f1a19 100644 --- a/src/Appwrite/Platform/Tasks/Hamster.php +++ b/src/Appwrite/Platform/Tasks/Hamster.php @@ -4,17 +4,17 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Network\Validator\Origin; use Exception; -use Utopia\App; -use Utopia\Platform\Action; -use Utopia\Cache\Cache; -use Utopia\CLI\Console; -use Utopia\Database\Database; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Analytics\Adapter\Mixpanel; use Utopia\Analytics\Event; +use Utopia\App; +use Utopia\Cache\Cache; +use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; use Utopia\Pools\Group; class Hamster extends Action @@ -67,7 +67,8 @@ class Hamster extends Action * Skip user projects with id 'console' */ if ($project->getId() === 'console') { - Console::info("Skipping project console"); + Console::info('Skipping project console'); + return; } @@ -82,7 +83,7 @@ class Hamster extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase('appwrite'); - $dbForProject->setNamespace('_' . $project->getInternalId()); + $dbForProject->setNamespace('_'.$project->getInternalId()); $statsPerProject = []; @@ -101,7 +102,7 @@ class Hamster extends Action $statsPerProject['custom_functions'] = $dbForProject->count('functions', [], APP_LIMIT_COUNT); foreach (\array_keys(Config::getParam('runtimes')) as $runtime) { - $statsPerProject['custom_functions_' . $runtime] = $dbForProject->count('functions', [ + $statsPerProject['custom_functions_'.$runtime] = $dbForProject->count('functions', [ Query::equal('runtime', [$runtime]), ], APP_LIMIT_COUNT); } @@ -116,7 +117,7 @@ class Hamster extends Action $teamInternalId = $project->getAttribute('teamInternalId', null); if ($teamInternalId) { $statsPerProject['custom_organization_members'] = $dbForConsole->count('memberships', [ - Query::equal('teamInternalId', [$teamInternalId]) + Query::equal('teamInternalId', [$teamInternalId]), ], APP_LIMIT_COUNT); } else { $statsPerProject['custom_organization_members'] = 0; @@ -128,8 +129,8 @@ class Hamster extends Action Query::equal('teamInternalId', [$teamInternalId]), ]); - if (!$membership || $membership->isEmpty()) { - throw new Exception('Membership not found. Skipping project : ' . $project->getId()); + if (! $membership || $membership->isEmpty()) { + throw new Exception('Membership not found. Skipping project : '.$project->getId()); } $userInternalId = $membership->getAttribute('userInternalId', null); @@ -146,42 +147,42 @@ class Hamster extends Action /** Get Domains */ $statsPerProject['custom_domains'] = $dbForConsole->count('domains', [ Query::equal('projectInternalId', [$project->getInternalId()]), - Query::limit(APP_LIMIT_COUNT) + Query::limit(APP_LIMIT_COUNT), ]); /** Get Platforms */ $platforms = $dbForConsole->find('platforms', [ Query::equal('projectInternalId', [$project->getInternalId()]), - Query::limit(APP_LIMIT_COUNT) + Query::limit(APP_LIMIT_COUNT), ]); - $statsPerProject['custom_platforms_web'] = sizeof(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_web'] = count(array_filter($platforms, function ($platform) { return $platform['type'] === 'web'; })); - $statsPerProject['custom_platforms_android'] = sizeof(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_android'] = count(array_filter($platforms, function ($platform) { return $platform['type'] === 'android'; })); - $statsPerProject['custom_platforms_apple'] = sizeof(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_apple'] = count(array_filter($platforms, function ($platform) { return str_contains($platform['type'], 'apple'); })); - $statsPerProject['custom_platforms_flutter'] = sizeof(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_flutter'] = count(array_filter($platforms, function ($platform) { return str_contains($platform['type'], 'flutter'); })); $flutterPlatforms = [Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_FLUTTER_LINUX]; foreach ($flutterPlatforms as $flutterPlatform) { - $statsPerProject['custom_platforms_' . $flutterPlatform] = sizeof(array_filter($platforms, function ($platform) use ($flutterPlatform) { + $statsPerProject['custom_platforms_'.$flutterPlatform] = count(array_filter($platforms, function ($platform) use ($flutterPlatform) { return $platform['type'] === $flutterPlatform; })); } $statsPerProject['custom_platforms_api_keys'] = $dbForConsole->count('keys', [ Query::equal('projectInternalId', [$project->getInternalId()]), - Query::limit(APP_LIMIT_COUNT) + Query::limit(APP_LIMIT_COUNT), ]); /** Get Usage $statsPerProject */ @@ -209,17 +210,17 @@ class Hamster extends Action Query::orderDesc('time'), ]); - $statsPerProject[$key . '_' . $periodKey] = []; + $statsPerProject[$key.'_'.$periodKey] = []; foreach ($requestDocs as $requestDoc) { - $statsPerProject[$key . '_' . $periodKey][] = [ + $statsPerProject[$key.'_'.$periodKey][] = [ 'value' => $requestDoc->getAttribute('value'), 'date' => $requestDoc->getAttribute('time'), ]; } - $statsPerProject[$key . '_' . $periodKey] = array_reverse($statsPerProject[$key . '_' . $periodKey]); + $statsPerProject[$key.'_'.$periodKey] = array_reverse($statsPerProject[$key.'_'.$periodKey]); // Calculate aggregate of each metric - $statsPerProject[$key . '_' . $periodKey] = array_sum(array_column($statsPerProject[$key . '_' . $periodKey], 'value')); + $statsPerProject[$key.'_'.$periodKey] = array_sum(array_column($statsPerProject[$key.'_'.$periodKey], 'value')); } } }); @@ -228,11 +229,11 @@ class Hamster extends Action /** Send data to mixpanel */ $res = $this->mixpanel->createProfile($statsPerProject['email'], '', [ 'name' => $statsPerProject['name'], - 'email' => $statsPerProject['email'] + 'email' => $statsPerProject['email'], ]); - if (!$res) { - Console::error('Failed to create user profile for project: ' . $project->getId()); + if (! $res) { + Console::error('Failed to create user profile for project: '.$project->getId()); } $event = new Event(); @@ -240,12 +241,12 @@ class Hamster extends Action ->setName('Project Daily Usage') ->setProps($statsPerProject); $res = $this->mixpanel->createEvent($event); - if (!$res) { - Console::error('Failed to create event for project: ' . $project->getId()); + if (! $res) { + Console::error('Failed to create event for project: '.$project->getId()); } } } catch (Exception $e) { - Console::error('Failed to send stats for project: ' . $project->getId()); + Console::error('Failed to send stats for project: '.$project->getId()); Console::error($e->getMessage()); } finally { $pools @@ -257,9 +258,8 @@ class Hamster extends Action public function action(Group $pools, Cache $cache, Database $dbForConsole): void { - Console::title('Cloud Hamster V1'); - Console::success(APP_NAME . ' cloud hamster process has started'); + Console::success(APP_NAME.' cloud hamster process has started'); $sleep = (int) App::getEnv('_APP_HAMSTER_INTERVAL', '30'); // 30 seconds (by default) @@ -278,7 +278,7 @@ class Hamster extends Action $delay = $next->getTimestamp() - $now->getTimestamp(); } - Console::log('[' . $now->format("Y-m-d H:i:s.v") . '] Delaying for ' . $delay . ' setting loop to [' . $next->format("Y-m-d H:i:s.v") . ']'); + Console::log('['.$now->format('Y-m-d H:i:s.v').'] Delaying for '.$delay.' setting loop to ['.$next->format('Y-m-d H:i:s.v').']'); Console::loop(function () use ($pools, $cache, $dbForConsole, $sleep) { $now = date('d-m-Y H:i:s', time()); @@ -325,12 +325,12 @@ class Hamster extends Action $results = $dbForConsole->find($collection, \array_merge([ Query::limit($limit), - Query::offset($count) + Query::offset($count), ])); $sum = count($results); - Console::log('Processing chunk #' . $chunk . '. Found ' . $sum . ' documents'); + Console::log('Processing chunk #'.$chunk.'. Found '.$sum.' documents'); foreach ($results as $document) { call_user_func($callback, $dbForConsole, $document); @@ -340,12 +340,11 @@ class Hamster extends Action $executionEnd = \microtime(true); - Console::log("Processed {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); + Console::log("Processed {$count} document by group in ".($executionEnd - $executionStart).' seconds'); } protected function getStatsPerOrganization(Database $dbForConsole) { - $this->calculateByGroup('teams', $dbForConsole, function (Database $dbForConsole, Document $document) { try { $statsPerOrganization = []; @@ -358,8 +357,8 @@ class Hamster extends Action Query::equal('teamInternalId', [$document->getInternalId()]), ]); - if (!$membership || $membership->isEmpty()) { - throw new Exception('Membership not found. Skipping organization : ' . $document->getId()); + if (! $membership || $membership->isEmpty()) { + throw new Exception('Membership not found. Skipping organization : '.$document->getId()); } $userInternalId = $membership->getAttribute('userInternalId', null); @@ -380,11 +379,11 @@ class Hamster extends Action /** Number of projects in this organization */ $statsPerOrganization['projects'] = $dbForConsole->count('projects', [ Query::equal('teamId', [$document->getId()]), - Query::limit(APP_LIMIT_COUNT) + Query::limit(APP_LIMIT_COUNT), ]); - if (!isset($statsPerOrganization['email'])) { - throw new Exception('Email not found. Skipping organization : ' . $document->getId()); + if (! isset($statsPerOrganization['email'])) { + throw new Exception('Email not found. Skipping organization : '.$document->getId()); } $event = new Event(); @@ -392,8 +391,8 @@ class Hamster extends Action ->setName('Organization Daily Usage') ->setProps($statsPerOrganization); $res = $this->mixpanel->createEvent($event); - if (!$res) { - throw new Exception('Failed to create event for organization : ' . $document->getId()); + if (! $res) { + throw new Exception('Failed to create event for organization : '.$document->getId()); } } catch (Exception $e) { Console::error($e->getMessage()); @@ -419,11 +418,11 @@ class Hamster extends Action /** Number of teams this user is a part of */ $statsPerUser['memberships'] = $dbForConsole->count('memberships', [ Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_COUNT) + Query::limit(APP_LIMIT_COUNT), ]); - if (!isset($statsPerUser['email'])) { - throw new Exception('User has no email: ' . $document->getId()); + if (! isset($statsPerUser['email'])) { + throw new Exception('User has no email: '.$document->getId()); } /** Send data to mixpanel */ @@ -433,8 +432,8 @@ class Hamster extends Action ->setProps($statsPerUser); $res = $this->mixpanel->createEvent($event); - if (!$res) { - throw new Exception('Failed to create user profile for user: ' . $document->getId()); + if (! $res) { + throw new Exception('Failed to create user profile for user: '.$document->getId()); } } catch (Exception $e) { Console::error($e->getMessage()); diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index be12eadf62..9c25320b6d 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -9,8 +9,8 @@ use Appwrite\Utopia\View; use Utopia\Analytics\GoogleAnalytics; use Utopia\CLI\Console; use Utopia\Config\Config; -use Utopia\Validator\Text; use Utopia\Platform\Action; +use Utopia\Validator\Text; class Install extends Action { @@ -70,19 +70,19 @@ class Install extends Action Console::success('Starting Appwrite installation...'); // Create directory with write permissions - if (null !== $path && !\file_exists(\dirname($path))) { - if (!@\mkdir(\dirname($path), 0755, true)) { - Console::error('Can\'t create directory ' . \dirname($path)); + if (null !== $path && ! \file_exists(\dirname($path))) { + if (! @\mkdir(\dirname($path), 0755, true)) { + Console::error('Can\'t create directory '.\dirname($path)); Console::exit(1); } } - $data = @file_get_contents($path . '/docker-compose.yml'); + $data = @file_get_contents($path.'/docker-compose.yml'); if ($data !== false) { $time = \time(); - Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); - file_put_contents($path . '/docker-compose.yml.' . $time . '.backup', $data); + Console::info('Compose file found, creating backup: docker-compose.yml.'.$time.'.backup'); + file_put_contents($path.'/docker-compose.yml.'.$time.'.backup', $data); $compose = new Compose($data); $appwrite = $compose->getService('appwrite'); $oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null; @@ -91,14 +91,14 @@ class Install extends Action } catch (\Throwable $th) { $ports = [ $defaultHTTPPort => $defaultHTTPPort, - $defaultHTTPSPort => $defaultHTTPSPort + $defaultHTTPSPort => $defaultHTTPSPort, ]; Console::warning('Traefik not found. Falling back to default ports.'); } if ($oldVersion) { foreach ($compose->getServices() as $service) { // Fetch all env vars from previous compose file - if (!$service) { + if (! $service) { continue; } @@ -116,11 +116,11 @@ class Install extends Action } } - $data = @file_get_contents($path . '/.env'); + $data = @file_get_contents($path.'/.env'); if ($data !== false) { // Fetch all env vars from previous .env file - Console::info('Env file found, creating backup: .env.' . $time . '.backup'); - file_put_contents($path . '/.env.' . $time . '.backup', $data); + Console::info('Env file found, creating backup: .env.'.$time.'.backup'); + file_put_contents($path.'/.env.'.$time.'.backup', $data); $env = new Env($data); foreach ($env->list() as $key => $value) { @@ -148,40 +148,44 @@ class Install extends Action } if (empty($httpPort)) { - $httpPort = Console::confirm('Choose your server HTTP port: (default: ' . $defaultHTTPPort . ')'); + $httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')'); $httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort; } if (empty($httpsPort)) { - $httpsPort = Console::confirm('Choose your server HTTPS port: (default: ' . $defaultHTTPSPort . ')'); + $httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')'); $httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort; } $input = []; foreach ($vars as $var) { - if (!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) { + if (! empty($var['filter']) && ($interactive !== 'Y' || ! Console::isInteractive())) { if ($data && $var['default'] !== null) { $input[$var['name']] = $var['default']; + continue; } if ($var['filter'] === 'token') { $input[$var['name']] = Auth::tokenGenerator(); + continue; } if ($var['filter'] === 'password') { $input[$var['name']] = Auth::passwordGenerator(); + continue; } } - if (!$var['required'] || !Console::isInteractive() || $interactive !== 'Y') { + if (! $var['required'] || ! Console::isInteractive() || $interactive !== 'Y') { $input[$var['name']] = $var['default']; + continue; } - $input[$var['name']] = Console::confirm($var['question'] . ' (default: \'' . $var['default'] . '\')'); + $input[$var['name']] = Console::confirm($var['question'].' (default: \''.$var['default'].'\')'); if (empty($input[$var['name']])) { $input[$var['name']] = $var['default']; @@ -191,38 +195,36 @@ class Install extends Action if ($input[$var['name']] !== 'localhost') { Console::warning("\nIf you haven't already done so, set the following record for {$input[$var['name']]} on your DNS provider:\n"); $mask = "%-15.15s %-10.10s %-30.30s\n"; - printf($mask, "Type", "Name", "Value"); - printf($mask, "A or AAAA", "@", ""); + printf($mask, 'Type', 'Name', 'Value'); + printf($mask, 'A or AAAA', '@', ''); Console::warning("\nUse 'AAAA' if you're using an IPv6 address and 'A' if you're using an IPv4 address.\n"); } } } - $templateForCompose = new View(__DIR__ . '/../views/install/compose.phtml'); - $templateForEnv = new View(__DIR__ . '/../views/install/env.phtml'); + $templateForCompose = new View(__DIR__.'/../views/install/compose.phtml'); + $templateForEnv = new View(__DIR__.'/../views/install/env.phtml'); $templateForCompose ->setParam('httpPort', $httpPort) ->setParam('httpsPort', $httpsPort) ->setParam('version', APP_VERSION_STABLE) ->setParam('organization', $organization) - ->setParam('image', $image) - ; + ->setParam('image', $image); $templateForEnv - ->setParam('vars', $input) - ; + ->setParam('vars', $input); - if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { + if (! file_put_contents($path.'/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); Console::error($message); Console::exit(1); } - if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { + if (! file_put_contents($path.'/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); Console::error($message); Console::exit(1); } @@ -233,23 +235,23 @@ class Install extends Action foreach ($input as $key => $value) { if ($value) { - $env .= $key . '=' . \escapeshellarg($value) . ' '; + $env .= $key.'='.\escapeshellarg($value).' '; } } - Console::log("Running \"docker compose up -d --remove-orphans --renew-anon-volumes\""); + Console::log('Running "docker compose up -d --remove-orphans --renew-anon-volumes"'); $exit = Console::execute("${env} docker compose --project-directory {$path} up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr); if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); Console::error($message); Console::error($stderr); Console::exit($exit); } else { $message = 'Appwrite installed successfully'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); Console::success($message); } } diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index 0739923e34..df93feb4af 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -2,14 +2,13 @@ namespace Appwrite\Platform\Tasks; -use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Platform\Action; @@ -31,7 +30,7 @@ class Maintenance extends Action public function action(Database $dbForConsole): void { Console::title('Maintenance V1'); - Console::success(APP_NAME . ' maintenance process v1 has started'); + Console::success(APP_NAME.' maintenance process v1 has started'); function notifyDeleteExecutionLogs(int $interval) { @@ -85,20 +84,19 @@ class Maintenance extends Action $time = DateTime::now(); $certificates = $dbForConsole->find('certificates', [ - Query::lessThan('attempts', 5), // Maximum 5 attempts - Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) - Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains) + Query::lessThan('attempts', 5), // Maximum 5 attempts + Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) + Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains) ]); - if (\count($certificates) > 0) { - Console::info("[{$time}] Found " . \count($certificates) . " certificates for renewal, scheduling jobs."); + Console::info("[{$time}] Found ".\count($certificates).' certificates for renewal, scheduling jobs.'); $event = new Certificate(); foreach ($certificates as $certificate) { $event ->setDomain(new Document([ - 'domain' => $certificate->getAttribute('domain') + 'domain' => $certificate->getAttribute('domain'), ])) ->trigger(); } @@ -109,7 +107,6 @@ class Maintenance extends Action function notifyDeleteCache($interval) { - (new Delete()) ->setType(DELETE_TYPE_CACHE_BY_TIMESTAMP) ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) @@ -118,7 +115,6 @@ class Maintenance extends Action function notifyDeleteSchedules($interval) { - (new Delete()) ->setType(DELETE_TYPE_SCHEDULES) ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 90b4234109..b4112f8d3f 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -2,14 +2,14 @@ namespace Appwrite\Platform\Tasks; -use Utopia\Platform\Action; -use Utopia\CLI\Console; use Appwrite\Migration\Migration; use Utopia\App; -use Utopia\Cache\Cache; use Utopia\Cache\Adapter\Redis as RedisCache; +use Utopia\Cache\Cache; +use Utopia\CLI\Console; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; use Utopia\Registry\Registry; use Utopia\Validator\Text; @@ -35,22 +35,23 @@ class Migrate extends Action try { $redis->del($redis->keys("cache-_{$project->getInternalId()}:*")); } catch (\Throwable $th) { - Console::error('Failed to clear project ("' . $project->getId() . '") cache with error: ' . $th->getMessage()); + Console::error('Failed to clear project ("'.$project->getId().'") cache with error: '.$th->getMessage()); } } public function action(string $version, Registry $register) { Authorization::disable(); - if (!array_key_exists($version, Migration::$versions)) { + if (! array_key_exists($version, Migration::$versions)) { Console::error("Version {$version} not found."); Console::exit(1); + return; } $app = new App('UTC'); - Console::success('Starting Data Migration to version ' . $version); + Console::success('Starting Data Migration to version '.$version); $dbPool = $register->get('dbPool', true); $redis = $register->get('cache', true); @@ -78,10 +79,10 @@ class Migrate extends Action $totalProjects = $dbForConsole->count('projects') + 1; } - $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; + $class = 'Appwrite\\Migration\\Version\\'.Migration::$versions[$version]; $migration = new $class(); - while (!empty($projects)) { + while (! empty($projects)) { foreach ($projects as $project) { /** * Skip user projects with id 'console' @@ -99,7 +100,7 @@ class Migrate extends Action ->setProject($project, $projectDB, $dbForConsole) ->execute(); } catch (\Throwable $th) { - Console::error('Failed to update project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); + Console::error('Failed to update project ("'.$project->getId().'") version with error: '.$th->getMessage()); throw $th; } @@ -112,7 +113,7 @@ class Migrate extends Action $offset = $offset + $limit; $count = $count + $sum; - Console::log('Migrated ' . $count . '/' . $totalProjects . ' projects...'); + Console::log('Migrated '.$count.'/'.$totalProjects.' projects...'); } Swoole\Event::wait(); // Wait for Coroutines to finish diff --git a/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php b/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php index 74ef644498..9724818f70 100644 --- a/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php +++ b/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php @@ -2,14 +2,14 @@ namespace Appwrite\Platform\Tasks; -use Utopia\Platform\Action; use Utopia\CLI\Console; +use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Query; -use Utopia\Database\Database; use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; class PatchCreateMissingSchedules extends Action { @@ -36,7 +36,7 @@ class PatchCreateMissingSchedules extends Action Authorization::setDefaultStatus(false); Console::title('PatchCreateMissingSchedules V1'); - Console::success(APP_NAME . ' PatchCreateMissingSchedules v1 has started'); + Console::success(APP_NAME.' PatchCreateMissingSchedules v1 has started'); $limit = 100; $projectCursor = null; @@ -52,7 +52,7 @@ class PatchCreateMissingSchedules extends Action } foreach ($projects as $project) { - Console::log("Checking Project " . $project->getAttribute('name') . " (" . $project->getId() . ")"); + Console::log('Checking Project '.$project->getAttribute('name').' ('.$project->getId().')'); $dbForProject = $getProjectDB($project); $functionCursor = null; @@ -79,11 +79,11 @@ class PatchCreateMissingSchedules extends Action 'resourceId' => $functionId, 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), - 'schedule' => $function->getAttribute('schedule'), - 'active' => !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment')), + 'schedule' => $function->getAttribute('schedule'), + 'active' => ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment')), ])); - Console::success('Recreated schedule for function ' . $functionId); + Console::success('Recreated schedule for function '.$functionId); } } diff --git a/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php b/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php index a909e68595..3a70e239cb 100644 --- a/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php +++ b/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php @@ -3,11 +3,11 @@ namespace Appwrite\Platform\Tasks; use Utopia\App; -use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Query; +use Utopia\Platform\Action; use Utopia\Pools\Group; use Utopia\Validator\Numeric; @@ -31,7 +31,6 @@ class PatchDeleteProjectCollections extends Action public function __construct() { - $this ->desc('Delete unnecessary project collections') ->param('offset', 0, new Numeric(), 'Resume deletion from param pos', true) @@ -48,7 +47,7 @@ class PatchDeleteProjectCollections extends Action //docker compose exec -t appwrite patch-delete-project-collections Console::title('Delete project collections V1'); - Console::success(APP_NAME . ' delete project collections has started'); + Console::success(APP_NAME.' delete project collections has started'); /* Initialise new Utopia app */ $app = new App('UTC'); @@ -63,9 +62,8 @@ class PatchDeleteProjectCollections extends Action $limit = 50; $sum = 50; $offset = $offset; - while (!empty($projects)) { + while (! empty($projects)) { foreach ($projects as $project) { - /** * Skip user projects with id 'console' */ @@ -84,7 +82,7 @@ class PatchDeleteProjectCollections extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $dbForProject->setNamespace('_' . $project->getInternalId()); + $dbForProject->setNamespace('_'.$project->getInternalId()); foreach ($this->names as $name) { if (empty($name)) { @@ -92,14 +90,14 @@ class PatchDeleteProjectCollections extends Action } if ($dbForProject->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { if ($dbForProject->deleteCollection($name)) { - Console::log('Deleted ' . $name); + Console::log('Deleted '.$name); } else { - Console::error('Failed to delete ' . $name); + Console::error('Failed to delete '.$name); } } } } catch (\Throwable $th) { - Console::error('Failed on project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); + Console::error('Failed on project ("'.$project->getId().'") version with error: '.$th->getMessage()); } finally { $pools ->get($db) @@ -114,14 +112,14 @@ class PatchDeleteProjectCollections extends Action Query::offset($offset), ]); - if (!empty($projects)) { - Console::log('Querying..... offset=' . $offset . ' , limit=' . $limit . ', count=' . $count); + if (! empty($projects)) { + Console::log('Querying..... offset='.$offset.' , limit='.$limit.', count='.$count); } $offset = $offset + $limit; $count = $count + $sum; } - Console::log('Iterated through ' . $count - 1 . '/' . $totalProjects . ' projects...'); + Console::log('Iterated through '.$count - 1 .'/'.$totalProjects.' projects...'); $pools ->get('console') ->reclaim(); diff --git a/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php b/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php index 95a7c4ffe1..b8fd8baaa2 100644 --- a/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php +++ b/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Tasks; -use Utopia\Platform\Action; use Utopia\CLI\Console; -use Utopia\Database\Query; use Utopia\Database\Database; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; use Utopia\Pools\Group; class PatchDeleteScheduleUpdatedAtAttribute extends Action @@ -35,7 +35,7 @@ class PatchDeleteScheduleUpdatedAtAttribute extends Action Authorization::setDefaultStatus(false); Console::title('PatchDeleteScheduleUpdatedAtAttribute V1'); - Console::success(APP_NAME . ' PatchDeleteScheduleUpdatedAtAttribute v1 has started'); + Console::success(APP_NAME.' PatchDeleteScheduleUpdatedAtAttribute v1 has started'); $limit = 100; $projectCursor = null; @@ -51,7 +51,7 @@ class PatchDeleteScheduleUpdatedAtAttribute extends Action } foreach ($projects as $project) { - Console::log("Checking Project " . $project->getAttribute('name') . " (" . $project->getId() . ")"); + Console::log('Checking Project '.$project->getAttribute('name').' ('.$project->getId().')'); $dbForProject = $getProjectDB($project); try { diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index f70ae8bd60..4b2c07e17c 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -2,8 +2,8 @@ namespace Appwrite\Platform\Tasks; -use Utopia\Platform\Action; use Appwrite\SDK\Language\Android; +use Appwrite\SDK\Language\Apple; use Appwrite\SDK\Language\CLI; use Appwrite\SDK\Language\Dart; use Appwrite\SDK\Language\Deno; @@ -18,14 +18,14 @@ use Appwrite\SDK\Language\Python; use Appwrite\SDK\Language\REST; use Appwrite\SDK\Language\Ruby; use Appwrite\SDK\Language\Swift; -use Exception; -use Throwable; -use Appwrite\SDK\Language\Apple; use Appwrite\SDK\Language\Web; use Appwrite\SDK\SDK; use Appwrite\Spec\Swagger2; +use Exception; +use Throwable; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Platform\Action; class SDKs extends Action { @@ -44,14 +44,14 @@ class SDKs extends Action public function action(): void { $platforms = Config::getParam('platforms'); - $selectedPlatform = Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); + $selectedPlatform = Console::confirm('Choose Platform ("'.APP_PLATFORM_CLIENT.'", "'.APP_PLATFORM_SERVER.'", "'.APP_PLATFORM_CONSOLE.'" or "*" for all):'); $selectedSDK = \strtolower(Console::confirm('Choose SDK ("*" for all):')); $version = Console::confirm('Choose an Appwrite version'); $git = (Console::confirm('Should we use git push? (yes/no)') == 'yes'); $production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false; $message = ($git) ? Console::confirm('Please enter your commit message:') : ''; - if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', 'latest'])) { + if (! in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', 'latest'])) { throw new Exception('Unknown version given'); } @@ -65,30 +65,31 @@ class SDKs extends Action continue; } - if (!$language['enabled']) { - Console::warning($language['name'] . ' for ' . $platform['name'] . ' is disabled'); + if (! $language['enabled']) { + Console::warning($language['name'].' for '.$platform['name'].' is disabled'); + continue; } - Console::info('Fetching API Spec for ' . $language['name'] . ' for ' . $platform['name'] . ' (version: ' . $version . ')'); + Console::info('Fetching API Spec for '.$language['name'].' for '.$platform['name'].' (version: '.$version.')'); - $spec = file_get_contents(__DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $language['family'] . '.json'); + $spec = file_get_contents(__DIR__.'/../../../../app/config/specs/swagger2-'.$version.'-'.$language['family'].'.json'); $cover = 'https://appwrite.io/images/github.png'; - $result = \realpath(__DIR__ . '/../../../../app') . '/sdks/' . $key . '-' . $language['key']; - $resultExamples = \realpath(__DIR__ . '/../../../..') . '/docs/examples/' . $version . '/' . $key . '-' . $language['key']; - $target = \realpath(__DIR__ . '/../../../../app') . '/sdks/git/' . $language['key'] . '/'; - $readme = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/README.md'); + $result = \realpath(__DIR__.'/../../../../app').'/sdks/'.$key.'-'.$language['key']; + $resultExamples = \realpath(__DIR__.'/../../../..').'/docs/examples/'.$version.'/'.$key.'-'.$language['key']; + $target = \realpath(__DIR__.'/../../../../app').'/sdks/git/'.$language['key'].'/'; + $readme = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/README.md'); $readme = ($readme) ? \file_get_contents($readme) : ''; - $gettingStarted = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/GETTING_STARTED.md'); + $gettingStarted = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/GETTING_STARTED.md'); $gettingStarted = ($gettingStarted) ? \file_get_contents($gettingStarted) : ''; - $examples = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/EXAMPLES.md'); + $examples = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/EXAMPLES.md'); $examples = ($examples) ? \file_get_contents($examples) : ''; - $changelog = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/CHANGELOG.md'); + $changelog = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/CHANGELOG.md'); $changelog = ($changelog) ? \file_get_contents($changelog) : '# Change Log'; - $warning = '**This SDK is compatible with Appwrite server version ' . $version . '. For older versions, please check [previous releases](' . $language['url'] . '/releases).**'; + $warning = '**This SDK is compatible with Appwrite server version '.$version.'. For older versions, please check [previous releases]('.$language['url'].'/releases).**'; $license = 'BSD-3-Clause'; - $licenseContent = 'Copyright (c) ' . date('Y') . ' Appwrite (https://appwrite.io) and individual contributors. + $licenseContent = 'Copyright (c) '.date('Y').' Appwrite (https://appwrite.io) and individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -142,7 +143,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $config = new Node(); $config->setNPMPackage('node-appwrite'); $config->setBowerPackage('appwrite'); - $warning = $warning . "\n\n > This is the Node.js SDK for integrating with Appwrite from your Node.js server-side code. + $warning = $warning."\n\n > This is the Node.js SDK for integrating with Appwrite from your Node.js server-side code. If you're looking to integrate from the browser, you should check [appwrite/sdk-for-web](https://github.com/appwrite/sdk-for-web)"; break; case 'deno': @@ -168,14 +169,14 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND case 'dart': $config = new Dart(); $config->setPackageName('dart_appwrite'); - $warning = $warning . "\n\n > This is the Dart SDK for integrating with Appwrite from your Dart server-side code. If you're looking for the Flutter SDK you should check [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter)"; + $warning = $warning."\n\n > This is the Dart SDK for integrating with Appwrite from your Dart server-side code. If you're looking for the Flutter SDK you should check [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter)"; break; case 'go': $config = new Go(); break; case 'swift': $config = new Swift(); - $warning = $warning . "\n\n > This is the Swift SDK for integrating with Appwrite from your Swift server-side code. If you're looking for the Apple SDK you should check [appwrite/sdk-for-apple](https://github.com/appwrite/sdk-for-apple)"; + $warning = $warning."\n\n > This is the Swift SDK for integrating with Appwrite from your Swift server-side code. If you're looking for the Apple SDK you should check [appwrite/sdk-for-apple](https://github.com/appwrite/sdk-for-apple)"; break; case 'apple': $config = new Apple(); @@ -189,7 +190,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND break; case 'kotlin': $config = new Kotlin(); - $warning = $warning . "\n\n > This is the Kotlin SDK for integrating with Appwrite from your Kotlin server-side code. If you're looking for the Android SDK you should check [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android)"; + $warning = $warning."\n\n > This is the Kotlin SDK for integrating with Appwrite from your Kotlin server-side code. If you're looking for the Android SDK you should check [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android)"; break; case 'graphql': $config = new GraphQL(); @@ -198,7 +199,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $config = new REST(); break; default: - throw new Exception('Language "' . $language['key'] . '" not supported'); + throw new Exception('Language "'.$language['key'].'" not supported'); } Console::info("Generating {$language['name']} SDK..."); @@ -246,29 +247,28 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $gitUrl = $language['gitUrl']; $gitBranch = $language['gitBranch']; - - if (!$production) { - $gitUrl = 'git@github.com:aw-tests/' . $language['gitRepoName'] . '.git'; + if (! $production) { + $gitUrl = 'git@github.com:aw-tests/'.$language['gitRepoName'].'.git'; } - if ($git && !empty($gitUrl)) { - \exec('rm -rf ' . $target . ' && \ - mkdir -p ' . $target . ' && \ - cd ' . $target . ' && \ - git init --initial-branch=' . $gitBranch . ' && \ - git remote add origin ' . $gitUrl . ' && \ - git fetch origin ' . $gitBranch . ' && \ - git pull origin ' . $gitBranch . ' && \ - rm -rf ' . $target . '/* && \ - cp -r ' . $result . '/* ' . $target . '/ && \ + if ($git && ! empty($gitUrl)) { + \exec('rm -rf '.$target.' && \ + mkdir -p '.$target.' && \ + cd '.$target.' && \ + git init --initial-branch='.$gitBranch.' && \ + git remote add origin '.$gitUrl.' && \ + git fetch origin '.$gitBranch.' && \ + git pull origin '.$gitBranch.' && \ + rm -rf '.$target.'/* && \ + cp -r '.$result.'/* '.$target.'/ && \ git add . && \ - git commit -m "' . $message . '" && \ - git push -u origin ' . $gitBranch . ' + git commit -m "'.$message.'" && \ + git push -u origin '.$gitBranch.' '); Console::success("Pushed {$language['name']} SDK to {$gitUrl}"); - \exec('rm -rf ' . $target); + \exec('rm -rf '.$target); Console::success("Remove temp directory '{$target}' for {$language['name']} SDK"); } @@ -279,10 +279,10 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND } foreach ($docDirectories as $languageTitle => $path) { - $languagePath = strtolower($languageTitle !== 0 ? '/' . $languageTitle : ''); + $languagePath = strtolower($languageTitle !== 0 ? '/'.$languageTitle : ''); \exec( - 'mkdir -p ' . $resultExamples . $languagePath . ' && \ - cp -r ' . $result . '/docs/examples' . $languagePath . ' ' . $resultExamples + 'mkdir -p '.$resultExamples.$languagePath.' && \ + cp -r '.$result.'/docs/examples'.$languagePath.' '.$resultExamples ); Console::success("Copied code examples for {$language['name']} SDK to: {$resultExamples}"); } diff --git a/src/Appwrite/Platform/Tasks/SSL.php b/src/Appwrite/Platform/Tasks/SSL.php index 43026b0753..9697ff91ae 100644 --- a/src/Appwrite/Platform/Tasks/SSL.php +++ b/src/Appwrite/Platform/Tasks/SSL.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Tasks; -use Utopia\Platform\Action; use Appwrite\Event\Certificate; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Document; +use Utopia\Platform\Action; use Utopia\Validator\Hostname; class SSL extends Action @@ -26,11 +26,11 @@ class SSL extends Action public function action(string $domain): void { - Console::success('Scheduling a job to issue a TLS certificate for domain: ' . $domain); + Console::success('Scheduling a job to issue a TLS certificate for domain: '.$domain); (new Certificate()) ->setDomain(new Document([ - 'domain' => $domain + 'domain' => $domain, ])) ->setSkipRenewCheck(true) ->trigger(); diff --git a/src/Appwrite/Platform/Tasks/Schedule.php b/src/Appwrite/Platform/Tasks/Schedule.php index 219d1c9886..42e8327e9a 100644 --- a/src/Appwrite/Platform/Tasks/Schedule.php +++ b/src/Appwrite/Platform/Tasks/Schedule.php @@ -2,23 +2,23 @@ namespace Appwrite\Platform\Tasks; +use Appwrite\Event\Func; use Cron\CronExpression; +use function Swoole\Coroutine\run; use Swoole\Timer; use Utopia\App; -use Utopia\Platform\Action; use Utopia\CLI\Console; +use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Database; +use Utopia\Platform\Action; use Utopia\Pools\Group; -use Appwrite\Event\Func; - -use function Swoole\Coroutine\run; class Schedule extends Action { public const FUNCTION_UPDATE_TIMER = 10; //seconds + public const FUNCTION_ENQUEUE_TIMER = 60; //seconds public static function getName(): string @@ -40,16 +40,17 @@ class Schedule extends Action * 1. Load all documents from 'schedules' collection to create local copy * 2. Create timer that sync all changes from 'schedules' collection to local copy. Only reading changes thanks to 'resourceUpdatedAt' attribute * 3. Create timer that prepares coroutines for soon-to-execute schedules. When it's ready, coroutime sleeps until exact time before sending request to worker. - */ + */ public function action(Group $pools, Database $dbForConsole, callable $getProjectDB): void { Console::title('Scheduler V1'); - Console::success(APP_NAME . ' Scheduler v1 has started'); + Console::success(APP_NAME.' Scheduler v1 has started'); /** * Extract only nessessary attributes to lower memory used. * * @var Document $schedule + * * @return array */ $getSchedule = function (Document $schedule) use ($dbForConsole, $getProjectDB): array { @@ -92,14 +93,14 @@ class Schedule extends Action $schedules[$document['resourceId']] = $getSchedule($document); } - $latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null; + $latestDocument = ! empty(array_key_last($results)) ? $results[array_key_last($results)] : null; } $pools->reclaim(); - Console::success("{$total} functions were loaded in " . (microtime(true) - $loadStart) . " seconds"); + Console::success("{$total} functions were loaded in ".(microtime(true) - $loadStart).' seconds'); - Console::success("Starting timers at " . DateTime::now()); + Console::success('Starting timers at '.DateTime::now()); run( function () use ($dbForConsole, &$schedules, &$lastSyncUpdate, $getSchedule, $pools) { @@ -120,7 +121,7 @@ class Schedule extends Action while ($sum === $limit) { $paginationQueries = [Query::limit($limit)]; if ($latestDocument !== null) { - $paginationQueries[] = Query::cursorAfter($latestDocument); + $paginationQueries[] = Query::cursorAfter($latestDocument); } $results = $dbForConsole->find('schedules', \array_merge($paginationQueries, [ Query::equal('region', [App::getEnv('_APP_REGION', 'default')]), @@ -144,7 +145,7 @@ class Schedule extends Action $schedules[$document['resourceId']] = $getSchedule($document); } } - $latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null; + $latestDocument = ! empty(array_key_last($results)) ? $results[array_key_last($results)] : null; } $lastSyncUpdate = $time; @@ -152,7 +153,7 @@ class Schedule extends Action $pools->reclaim(); - Console::log("Sync tick: {$total} schedules were updated in " . ($timerEnd - $timerStart) . " seconds"); + Console::log("Sync tick: {$total} schedules were updated in ".($timerEnd - $timerStart).' seconds'); }); /** @@ -179,7 +180,7 @@ class Schedule extends Action $currentTick = $next < $timeFrame; - if (!$currentTick) { + if (! $currentTick) { continue; } @@ -189,7 +190,7 @@ class Schedule extends Action $executionStart = $nextDate->getTimestamp(); // in seconds $delay = $executionStart - $promiseStart; // Time to wait from now until execution needs to be queued - if (!isset($delayedExecutions[$delay])) { + if (! isset($delayedExecutions[$delay])) { $delayedExecutions[$delay] = []; } @@ -205,7 +206,7 @@ class Schedule extends Action foreach ($scheduleKeys as $scheduleKey) { // Ensure schedule was not deleted - if (!isset($schedules[$scheduleKey])) { + if (! isset($schedules[$scheduleKey])) { return; } @@ -226,10 +227,10 @@ class Schedule extends Action $timerEnd = \microtime(true); $lastEnqueueUpdate = $timerStart; - Console::log("Enqueue tick: {$total} executions were enqueued in " . ($timerEnd - $timerStart) . " seconds"); + Console::log("Enqueue tick: {$total} executions were enqueued in ".($timerEnd - $timerStart).' seconds'); }; - Timer::tick(self::FUNCTION_ENQUEUE_TIMER * 1000, fn() => $enqueueFunctions()); + Timer::tick(self::FUNCTION_ENQUEUE_TIMER * 1000, fn () => $enqueueFunctions()); $enqueueFunctions(); } ); diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index 82caf8ef72..d596a36925 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Tasks; -use Utopia\Platform\Action; -use Utopia\Validator\Text; use Appwrite\Specification\Format\OpenAPI3; use Appwrite\Specification\Format\Swagger2; use Appwrite\Specification\Specification; @@ -17,8 +15,10 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Adapter\MySQL; use Utopia\Database\Database; +use Utopia\Platform\Action; use Utopia\Registry\Registry; use Utopia\Request; +use Utopia\Validator\Text; use Utopia\Validator\WhiteList; class Specs extends Action @@ -177,15 +177,15 @@ class Specs extends Action $sdkPlaforms[] = APP_PLATFORM_CLIENT; } - if (!$route->getLabel('docs', true)) { + if (! $route->getLabel('docs', true)) { continue; } - if ($route->getLabel('sdk.mock', false) && !$mocks) { + if ($route->getLabel('sdk.mock', false) && ! $mocks) { continue; } - if (!$route->getLabel('sdk.mock', false) && $mocks) { + if (! $route->getLabel('sdk.mock', false) && $mocks) { continue; } @@ -193,7 +193,7 @@ class Specs extends Action continue; } - if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlaforms)) { + if ($platform !== APP_PLATFORM_CONSOLE && ! \in_array($platforms[$platform], $sdkPlaforms)) { continue; } @@ -203,10 +203,10 @@ class Specs extends Action foreach (Config::getParam('services', []) as $service) { if ( - !isset($service['docs']) // Skip service if not part of the public API - || !isset($service['sdk']) - || !$service['docs'] - || !$service['sdk'] + ! isset($service['docs']) // Skip service if not part of the public API + || ! isset($service['sdk']) + || ! $service['docs'] + || ! $service['sdk'] ) { continue; } @@ -221,7 +221,7 @@ class Specs extends Action $models = $response->getModels(); foreach ($models as $key => $value) { - if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) { + if ($platform !== APP_PLATFORM_CONSOLE && ! $value->isPublic()) { unset($models[$key]); } } @@ -231,7 +231,7 @@ class Specs extends Action $formatInstance = match ($format) { 'swagger2' => new Swagger2(...$arguments), 'open-api3' => new OpenAPI3(...$arguments), - default => throw new Exception('Format not found: ' . $format) + default => throw new Exception('Format not found: '.$format) }; $specs = new Specification($formatInstance); @@ -243,36 +243,36 @@ class Specs extends Action ->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)') ->setParam('endpoint', 'https://HOSTNAME/v1') ->setParam('version', APP_VERSION_STABLE) - ->setParam('terms', $endpoint . '/policy/terms') + ->setParam('terms', $endpoint.'/policy/terms') ->setParam('support.email', $email) - ->setParam('support.url', $endpoint . '/support') - ->setParam('contact.name', APP_NAME . ' Team') + ->setParam('support.url', $endpoint.'/support') + ->setParam('contact.name', APP_NAME.' Team') ->setParam('contact.email', $email) - ->setParam('contact.url', $endpoint . '/support') + ->setParam('contact.url', $endpoint.'/support') ->setParam('license.name', 'BSD-3-Clause') ->setParam('license.url', 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE') ->setParam('docs.description', 'Full API docs, specs and tutorials') - ->setParam('docs.url', $endpoint . '/docs'); + ->setParam('docs.url', $endpoint.'/docs'); if ($mocks) { - $path = __DIR__ . '/../config/specs/' . $format . '-mocks-' . $platform . '.json'; + $path = __DIR__.'/../config/specs/'.$format.'-mocks-'.$platform.'.json'; - if (!file_put_contents($path, json_encode($specs->parse()))) { - throw new Exception('Failed to save mocks spec file: ' . $path); + if (! file_put_contents($path, json_encode($specs->parse()))) { + throw new Exception('Failed to save mocks spec file: '.$path); } - Console::success('Saved mocks spec file: ' . realpath($path)); + Console::success('Saved mocks spec file: '.realpath($path)); continue; } - $path = __DIR__ . '/../../../../app/config/specs/' . $format . '-' . $version . '-' . $platform . '.json'; + $path = __DIR__.'/../../../../app/config/specs/'.$format.'-'.$version.'-'.$platform.'.json'; - if (!file_put_contents($path, json_encode($specs->parse()))) { - throw new Exception('Failed to save spec file: ' . $path); + if (! file_put_contents($path, json_encode($specs->parse()))) { + throw new Exception('Failed to save spec file: '.$path); } - Console::success('Saved spec file: ' . realpath($path)); + Console::success('Saved spec file: '.realpath($path)); } } } diff --git a/src/Appwrite/Platform/Tasks/Vars.php b/src/Appwrite/Platform/Tasks/Vars.php index c97f77a9da..714bb40ab1 100644 --- a/src/Appwrite/Platform/Tasks/Vars.php +++ b/src/Appwrite/Platform/Tasks/Vars.php @@ -3,8 +3,8 @@ namespace Appwrite\Platform\Tasks; use Utopia\App; -use Utopia\Config\Config; use Utopia\CLI\Console; +use Utopia\Config\Config; use Utopia\Platform\Action; class Vars extends Action @@ -33,7 +33,7 @@ class Vars extends Action } foreach ($vars as $key => $value) { - Console::log('- ' . $value['name'] . '=' . App::getEnv($value['name'], '')); + Console::log('- '.$value['name'].'='.App::getEnv($value['name'], '')); } } } diff --git a/src/Appwrite/Platform/Tasks/VolumeSync.php b/src/Appwrite/Platform/Tasks/VolumeSync.php index 6197b20fbd..193d07fd17 100644 --- a/src/Appwrite/Platform/Tasks/VolumeSync.php +++ b/src/Appwrite/Platform/Tasks/VolumeSync.php @@ -27,11 +27,10 @@ class VolumeSync extends Action public function action(string $source, string $destination, int $interval) { - Console::title('RSync V1'); - Console::success(APP_NAME . ' rsync process v1 has started'); + Console::success(APP_NAME.' rsync process v1 has started'); - if (!file_exists($source)) { + if (! file_exists($source)) { Console::error('Source directory does not exist. Exiting ... '); Console::exit(0); } @@ -42,14 +41,15 @@ class VolumeSync extends Action Console::info("[{$time}] Executing rsync every {$interval} seconds"); Console::info("Syncing between $source and $destination"); - if (!file_exists($source)) { + if (! file_exists($source)) { Console::error('Source directory does not exist. Skipping ... '); + return; } - $stdin = ""; - $stdout = ""; - $stderr = ""; + $stdin = ''; + $stdout = ''; + $stderr = ''; Console::execute("rsync -av $source $destination", $stdin, $stdout, $stderr); Console::success($stdout); diff --git a/src/Appwrite/Promises/Promise.php b/src/Appwrite/Promises/Promise.php index a6b1aa79d5..95e4c7bc69 100644 --- a/src/Appwrite/Promises/Promise.php +++ b/src/Appwrite/Promises/Promise.php @@ -5,7 +5,9 @@ namespace Appwrite\Promises; abstract class Promise { protected const STATE_PENDING = 1; + protected const STATE_FULFILLED = 0; + protected const STATE_REJECTED = -1; protected int $state = self::STATE_PENDING; @@ -37,7 +39,7 @@ abstract class Promise /** * Create a new promise from the given callable. * - * @param callable $promise + * @param callable $promise * @return self */ public static function create(callable $promise): self @@ -48,7 +50,7 @@ abstract class Promise /** * Resolve promise with given value. * - * @param mixed $value + * @param mixed $value * @return self */ public static function resolve(mixed $value): self @@ -61,7 +63,7 @@ abstract class Promise /** * Rejects the promise with the given reason. * - * @param mixed $value + * @param mixed $value * @return self */ public static function reject(mixed $value): self @@ -74,7 +76,7 @@ abstract class Promise /** * Catch any exception thrown by the executor. * - * @param callable $onRejected + * @param callable $onRejected * @return self */ public function catch(callable $onRejected): self @@ -85,8 +87,8 @@ abstract class Promise /** * Execute the promise. * - * @param callable|null $onFulfilled - * @param callable|null $onRejected + * @param callable|null $onFulfilled + * @param callable|null $onRejected * @return self */ public function then( @@ -99,13 +101,15 @@ abstract class Promise if ($this->isFulfilled() && $onFulfilled === null) { return $this; } + return self::create(function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected) { while ($this->isPending()) { usleep(25000); } $callable = $this->isFulfilled() ? $onFulfilled : $onRejected; - if (!\is_callable($callable)) { + if (! \is_callable($callable)) { $resolve($this->result); + return; } try { @@ -119,7 +123,7 @@ abstract class Promise /** * Returns a promise that completes when all passed in promises complete. * - * @param iterable|self[] $promises + * @param iterable|self[] $promises * @return self */ abstract public static function all(iterable $promises): self; @@ -127,13 +131,14 @@ abstract class Promise /** * Set resolved result * - * @param mixed $value + * @param mixed $value * @return void */ protected function setResult(mixed $value): void { - if (!\is_callable([$value, 'then'])) { + if (! \is_callable([$value, 'then'])) { $this->result = $value; + return; } @@ -146,7 +151,7 @@ abstract class Promise $value->then($callable, $callable); - while (!$resolved) { + while (! $resolved) { usleep(25000); } } @@ -154,7 +159,7 @@ abstract class Promise /** * Change promise state * - * @param integer $state + * @param int $state * @return void */ protected function setState(int $state): void @@ -165,7 +170,7 @@ abstract class Promise /** * Promise is pending * - * @return boolean + * @return bool */ protected function isPending(): bool { @@ -175,7 +180,7 @@ abstract class Promise /** * Promise is fulfilled * - * @return boolean + * @return bool */ protected function isFulfilled(): bool { @@ -185,7 +190,7 @@ abstract class Promise /** * Promise is rejected * - * @return boolean + * @return bool */ protected function isRejected(): bool { diff --git a/src/Appwrite/Promises/Swoole.php b/src/Appwrite/Promises/Swoole.php index c258ef6a5e..4867ed6c96 100644 --- a/src/Appwrite/Promises/Swoole.php +++ b/src/Appwrite/Promises/Swoole.php @@ -28,7 +28,7 @@ class Swoole extends Promise /** * Returns a promise that completes when all passed in promises complete. * - * @param iterable|Swoole[] $promises + * @param iterable|Swoole[] $promises * @return Promise */ public static function all(iterable $promises): Promise @@ -45,6 +45,7 @@ class Swoole extends Promise $promise->then(function ($value) use ($key, &$result, $channel) { $result[$key] = $value; $channel->push(true); + return $value; }, function ($err) use ($channel, &$error) { $channel->push(true); @@ -61,6 +62,7 @@ class Swoole extends Promise if ($error !== null) { $reject($error); + return; } diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index 146500e743..f6ff7c2fb8 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -5,12 +5,14 @@ namespace Appwrite\Resque; use Appwrite\Event\Usage; use Exception; use Utopia\App; -use Utopia\Cache\Cache; -use Utopia\Config\Config; use Utopia\Cache\Adapter\Sharding; +use Utopia\Cache\Cache; use Utopia\CLI\Console; +use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Pools\Group; use Utopia\Storage\Device; use Utopia\Storage\Device\Backblaze; @@ -18,8 +20,6 @@ use Utopia\Storage\Device\DOSpaces; use Utopia\Storage\Device\Linode; use Utopia\Storage\Device\Local; use Utopia\Storage\Device\S3; -use Utopia\Database\Validator\Authorization; -use Utopia\DSN\DSN; use Utopia\Storage\Device\Wasabi; use Utopia\Storage\Storage; @@ -43,11 +43,12 @@ abstract class Worker * Function for identifying the worker needs to be set to unique name * * @return string + * * @throws Exception */ public function getName(): string { - throw new Exception("Please implement getName method in worker"); + throw new Exception('Please implement getName method in worker'); } /** @@ -55,11 +56,12 @@ abstract class Worker * Can include any preparations, such as connecting to external services or loading files * * @return void + * * @throws \Exception|\Throwable */ public function init(): void { - throw new Exception("Please implement init method in worker"); + throw new Exception('Please implement init method in worker'); } /** @@ -67,11 +69,12 @@ abstract class Worker * You can access $args here, it will contain event information * * @return void + * * @throws \Exception|\Throwable */ public function run(): void { - throw new Exception("Please implement run method in worker"); + throw new Exception('Please implement run method in worker'); } /** @@ -79,20 +82,23 @@ abstract class Worker * You can do cleanup here, such as disconnecting from services or removing temp files * * @return void + * * @throws \Exception|\Throwable */ public function shutdown(): void { - throw new Exception("Please implement shutdown method in worker"); + throw new Exception('Please implement shutdown method in worker'); } public const DATABASE_PROJECT = 'project'; + public const DATABASE_CONSOLE = 'console'; /** * A wrapper around 'init' function with non-worker-specific code * * @return void + * * @throws \Exception|\Throwable */ public function setUp(): void @@ -101,7 +107,7 @@ abstract class Worker $this->init(); } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { - $errorCallback($error, "init", $this->getName()); + $errorCallback($error, 'init', $this->getName()); } throw $error; @@ -112,6 +118,7 @@ abstract class Worker * A wrapper around 'run' function with non-worker-specific code * * @return void + * * @throws \Exception|\Throwable */ public function perform(): void @@ -125,7 +132,7 @@ abstract class Worker $this->run(); } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { - $errorCallback($error, "run", $this->getName(), $this->args); + $errorCallback($error, 'run', $this->getName(), $this->args); } throw $error; @@ -136,6 +143,7 @@ abstract class Worker * A wrapper around 'shutdown' function with non-worker-specific code * * @return void + * * @throws \Exception|\Throwable */ public function tearDown(): void @@ -149,17 +157,17 @@ abstract class Worker $this->shutdown(); } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { - $errorCallback($error, "shutdown", $this->getName()); + $errorCallback($error, 'shutdown', $this->getName()); } throw $error; } } - /** * Register callback. Will be executed when error occurs. - * @param callable $callback + * + * @param callable $callback * @return void */ public static function error(callable $callback): void @@ -169,8 +177,10 @@ abstract class Worker /** * Get internal project database - * @param Document $project + * + * @param Document $project * @return Database + * * @throws Exception */ protected static $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools @@ -180,7 +190,6 @@ abstract class Worker global $register; $pools = $register->get('pools'); /** @var Group $pools */ - if ($project->isEmpty() || $project->getId() === 'console') { return $this->getConsoleDB(); } @@ -189,28 +198,30 @@ abstract class Worker if (isset(self::$databases[$databaseName])) { $database = self::$databases[$databaseName]; - $database->setNamespace('_' . $project->getInternalId()); + $database->setNamespace('_'.$project->getInternalId()); + return $database; } $dbAdapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, $this->getCache()); self::$databases[$databaseName] = $database; - $database->setNamespace('_' . $project->getInternalId()); + $database->setNamespace('_'.$project->getInternalId()); return $database; } /** * Get console database + * * @return Database + * * @throws Exception */ protected function getConsoleDB(): Database @@ -218,20 +229,19 @@ abstract class Worker global $register; $pools = $register->get('pools'); /** @var Group $pools */ - $databaseName = 'console'; if (isset(self::$databases[$databaseName])) { $database = self::$databases[$databaseName]; $database->setNamespace('console'); + return $database; } $dbAdapter = $pools ->get('console') ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, $this->getCache()); @@ -242,9 +252,9 @@ abstract class Worker return $database; } - /** * Get Cache + * * @return Cache */ protected function getCache(): Cache @@ -252,7 +262,6 @@ abstract class Worker global $register; $pools = $register->get('pools'); /** @var Group $pools */ - $list = Config::getParam('pools-cache', []); $adapters = []; @@ -260,8 +269,7 @@ abstract class Worker $adapters[] = $pools ->get($value) ->pop() - ->getResource() - ; + ->getResource(); } return new Cache(new Sharding($adapters)); @@ -269,7 +277,9 @@ abstract class Worker /** * Get usage queue + * * @return Usage + * * @throws Exception */ protected function getUsageQueue(): Usage @@ -287,42 +297,46 @@ abstract class Worker /** * Get Functions Storage Device - * @param string $projectId of the project + * + * @param string $projectId of the project * @return Device */ protected function getFunctionsDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId); + return $this->getDevice(APP_STORAGE_FUNCTIONS.'/app-'.$projectId); } /** * Get Files Storage Device - * @param string $projectId of the project + * + * @param string $projectId of the project * @return Device */ protected function getFilesDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId); + return $this->getDevice(APP_STORAGE_UPLOADS.'/app-'.$projectId); } /** * Get Builds Storage Device - * @param string $projectId of the project + * + * @param string $projectId of the project * @return Device */ protected function getBuildsDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId); + return $this->getDevice(APP_STORAGE_BUILDS.'/app-'.$projectId); } protected function getCacheDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_CACHE . '/app-' . $projectId); + return $this->getDevice(APP_STORAGE_CACHE.'/app-'.$projectId); } /** * Get Device based on selected storage environment - * @param string $root path of the device + * + * @param string $root path of the device * @return Device */ public function getDevice(string $root): Device @@ -343,7 +357,7 @@ abstract class Worker $bucket = $dsn->getPath(); $region = $dsn->getParam('region'); } catch (\Exception $e) { - Console::error($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); + Console::error($e->getMessage().'Invalid DSN. Defaulting to Local device.'); } switch ($device) { diff --git a/src/Appwrite/Specification/Format.php b/src/Appwrite/Specification/Format.php index c2317c1153..670fbceecb 100644 --- a/src/Appwrite/Specification/Format.php +++ b/src/Appwrite/Specification/Format.php @@ -2,10 +2,10 @@ namespace Appwrite\Specification; +use Appwrite\Utopia\Response\Model; use Utopia\App; use Utopia\Config\Config; use Utopia\Route; -use Appwrite\Utopia\Response\Model; abstract class Format { @@ -22,8 +22,11 @@ abstract class Format protected array $models; protected array $services; + protected array $keys; + protected int $authCount; + protected array $params = [ 'name' => '', 'description' => '', @@ -46,8 +49,8 @@ abstract class Format [ 'namespace' => 'users', 'method' => 'getUsage', - 'parameter' => 'provider' - ] + 'parameter' => 'provider', + ], ]; public function __construct(App $app, array $services, array $routes, array $models, array $keys, int $authCount) @@ -83,9 +86,8 @@ abstract class Format * * Set param value * - * @param string $key - * @param string $value - * + * @param string $key + * @param string $value * @return self */ public function setParam(string $key, string $value): self @@ -100,9 +102,8 @@ abstract class Format * * Get param value * - * @param string $key - * @param string $default - * + * @param string $key + * @param string $default * @return string */ public function getParam(string $key, string $default = ''): string @@ -177,8 +178,10 @@ abstract class Format } break; } + return null; } + public function getEnumKeys(string $service, string $method, string $param): array { $values = []; @@ -190,18 +193,21 @@ abstract class Format foreach ($codes as $code => $value) { $values[] = $value['name']; } + return $values; case 'getCreditCard': $codes = Config::getParam('avatar-credit-cards'); foreach ($codes as $code => $value) { $values[] = $value['name']; } + return $values; case 'getFlag': $codes = Config::getParam('avatar-flags'); foreach ($codes as $code => $value) { $values[] = $value['name']; } + return $values; } break; @@ -211,7 +217,8 @@ abstract class Format case 'getCollectionUsage': case 'getDatabaseUsage': // Range Enum Keys - $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; + $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; + return $values; } break; @@ -221,6 +228,7 @@ abstract class Format case 'getFunctionUsage': // Range Enum Keys $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; + return $values; } break; @@ -231,6 +239,7 @@ abstract class Format // Range Enum Keys if ($param == 'range') { $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; + return $values; } } @@ -241,9 +250,11 @@ abstract class Format case 'getBucketUsage': // Range Enum Keys $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; + return $values; } } + return $values; } } diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 94cb0bb90d..f979ca1b4d 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -20,30 +20,32 @@ class OpenAPI3 extends Format protected function getNestedModels(Model $model, array &$usedModels): void { foreach ($model->getRules() as $rule) { - if (!in_array($model->getType(), $usedModels)) { + if (! in_array($model->getType(), $usedModels)) { continue; } if (\is_array($rule['type'])) { foreach ($rule['type'] as $ruleType) { - if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { + if (! in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { $usedModels[] = $ruleType; foreach ($this->models as $m) { if ($m->getType() === $ruleType) { $this->getNestedModels($m, $usedModels); + continue; } } } } } else { - if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { + if (! in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { $usedModels[] = $rule['type']; foreach ($this->models as $m) { if ($m->getType() === $rule['type']) { $this->getNestedModels($m, $usedModels); + continue; } } @@ -125,7 +127,7 @@ class OpenAPI3 extends Format } $id = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; + $desc = (! empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null; $produces = $route->getLabel('sdk.response.type', null); $model = $route->getLabel('sdk.response.model', 'none'); $routeSecurity = $route->getLabel('sdk.auth', []); @@ -154,7 +156,7 @@ class OpenAPI3 extends Format $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), + 'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id), 'tags' => [$route->getLabel('sdk.namespace', 'default')], 'description' => ($desc) ? \file_get_contents($desc) : '', 'responses' => [], @@ -163,8 +165,8 @@ class OpenAPI3 extends Format 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), 'type' => $route->getLabel('sdk.methodType', ''), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($id) . '.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), + 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master'.$route->getLabel('sdk.description', ''), 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), @@ -188,8 +190,8 @@ class OpenAPI3 extends Format } } - if (!(\is_array($model)) && $model->isNone()) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ + if (! (\is_array($model)) && $model->isNone()) { + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ 'description' => in_array($produces, [ 'image/*', 'image/jpeg', @@ -203,19 +205,19 @@ class OpenAPI3 extends Format ]; } else { if (\is_array($model)) { - $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + $modelDescription = \implode(', or ', \array_map(fn ($m) => $m->getName(), $model)); // model has multiple possible responses, we will use oneOf foreach ($model as $m) { $usedModels[] = $m->getType(); } - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ 'description' => $modelDescription, 'content' => [ $produces => [ 'schema' => [ - 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model) + 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/'.$m->getType()], $model), ], ], ], @@ -223,12 +225,12 @@ class OpenAPI3 extends Format } else { // Response definition using one type $usedModels[] = $model->getType(); - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'content' => [ $produces => [ 'schema' => [ - '$ref' => '#/components/schemas/' . $model->getType(), + '$ref' => '#/components/schemas/'.$model->getType(), ], ], ], @@ -237,11 +239,11 @@ class OpenAPI3 extends Format } if ($route->getLabel('sdk.response.code', 500) === 204) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; + unset($temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['schema']); } - if ((!empty($scope))) { // && 'public' != $scope + if ((! empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; foreach ($route->getLabel('sdk.auth', []) as $security) { @@ -256,8 +258,8 @@ class OpenAPI3 extends Format $body = [ 'content' => [ - $consumes[0] => [ - 'schema' => [ + $consumes[0] => [ + 'schema' => [ 'type' => 'object', 'properties' => [], ], @@ -276,7 +278,7 @@ class OpenAPI3 extends Format $node = [ 'name' => $name, 'description' => $param['description'], - 'required' => !$param['optional'], + 'required' => ! $param['optional'], ]; foreach ($this->services as $service) { @@ -292,10 +294,10 @@ class OpenAPI3 extends Format $validator = $validator->getValidator(); } - switch ((!empty($validator)) ? \get_class($validator) : '') { + switch ((! empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; + $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; break; case 'Utopia\Validator\Boolean': $node['schema']['type'] = $validator->getType(); @@ -303,14 +305,14 @@ class OpenAPI3 extends Format break; case 'Utopia\Database\Validator\UID': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; + $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; break; case 'Appwrite\Utopia\Database\Validator\CustomId': if ($route->getLabel('sdk.methodType', '') === 'upload') { $node['schema']['x-upload-id'] = true; } $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; + $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; break; case 'Utopia\Database\Validator\DatetimeValidator': $node['schema']['type'] = $validator->getType(); @@ -367,14 +369,14 @@ class OpenAPI3 extends Format $node['schema']['items'] = [ 'type' => 'string', ]; - $node['schema']['x-example'] = '["' . Permission::read(Role::any()) . '"]'; + $node['schema']['x-example'] = '["'.Permission::read(Role::any()).'"]'; break; case 'Utopia\Database\Validator\Roles': $node['schema']['type'] = $validator->getType(); $node['schema']['items'] = [ 'type' => 'string', ]; - $node['schema']['x-example'] = '["' . Role::any()->toString() . '"]'; + $node['schema']['x-example'] = '["'.Role::any()->toString().'"]'; break; case 'Appwrite\Auth\Validator\Password': $node['schema']['type'] = $validator->getType(); @@ -429,9 +431,9 @@ class OpenAPI3 extends Format } if ($allowed) { - $node['schema']['enum'] = $validator->getList(); - $node['schema']['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); - $node['schema']['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); + $node['schema']['enum'] = $validator->getList(); + $node['schema']['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); + $node['schema']['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); } if ($validator->getType() === 'integer') { $node['format'] = 'int32'; @@ -442,25 +444,25 @@ class OpenAPI3 extends Format break; } - if ($param['optional'] && !\is_null($param['default'])) { // Param has default value + if ($param['optional'] && ! \is_null($param['default'])) { // Param has default value $node['schema']['default'] = $param['default']; } - if (false !== \strpos($url, ':' . $name)) { // Param is in URL path + if (false !== \strpos($url, ':'.$name)) { // Param is in URL path $node['in'] = 'path'; $temp['parameters'][] = $node; } elseif ($route->getMethod() == 'GET') { // Param is in query $node['in'] = 'query'; $temp['parameters'][] = $node; } else { // Param is in payload - if (!$param['optional']) { + if (! $param['optional']) { $bodyRequired[] = $name; } $body['content'][$consumes[0]]['schema']['properties'][$name] = [ 'type' => $node['schema']['type'], 'description' => $node['description'], - 'x-example' => $node['schema']['x-example'] ?? null + 'x-example' => $node['schema']['x-example'] ?? null, ]; if (isset($node['schema']['enum'])) { @@ -491,14 +493,14 @@ class OpenAPI3 extends Format } } - $url = \str_replace(':' . $name, '{' . $name . '}', $url); + $url = \str_replace(':'.$name, '{'.$name.'}', $url); } - if (!empty($bodyRequired)) { + if (! empty($bodyRequired)) { $body['content'][$consumes[0]]['schema']['required'] = $bodyRequired; } - if (!empty($body['content'][$consumes[0]]['schema']['properties'])) { + if (! empty($body['content'][$consumes[0]]['schema']['properties'])) { $temp['requestBody'] = $body; } @@ -510,7 +512,7 @@ class OpenAPI3 extends Format } foreach ($this->models as $model) { - if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') { + if (! in_array($model->getType(), $usedModels) && $model->getType() !== 'error') { continue; } @@ -522,7 +524,7 @@ class OpenAPI3 extends Format 'type' => 'object', ]; - if (!empty($rules)) { + if (! empty($rules)) { $output['components']['schemas'][$model->getType()]['properties'] = []; } @@ -530,7 +532,7 @@ class OpenAPI3 extends Format $output['components']['schemas'][$model->getType()]['additionalProperties'] = true; } - if (!empty($required)) { + if (! empty($required)) { $output['components']['schemas'][$model->getType()]['required'] = $required; } @@ -577,19 +579,19 @@ class OpenAPI3 extends Format if ($rule['array']) { $items = [ 'anyOf' => \array_map(function ($type) { - return ['$ref' => '#/components/schemas/' . $type]; - }, $rule['type']) + return ['$ref' => '#/components/schemas/'.$type]; + }, $rule['type']), ]; } else { $items = [ 'oneOf' => \array_map(function ($type) { - return ['$ref' => '#/components/schemas/' . $type]; - }, $rule['type']) + return ['$ref' => '#/components/schemas/'.$type]; + }, $rule['type']), ]; } } else { $items = [ - '$ref' => '#/components/schemas/' . $rule['type'], + '$ref' => '#/components/schemas/'.$rule['type'], ]; } break; @@ -622,7 +624,7 @@ class OpenAPI3 extends Format if ($items) { $output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items; } - if (!in_array($name, $required)) { + if (! in_array($name, $required)) { $output['components']['schemas'][$model->getType()]['properties'][$name]['nullable'] = true; } } diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 6b3d394aad..15aad0238f 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -20,30 +20,32 @@ class Swagger2 extends Format protected function getNestedModels(Model $model, array &$usedModels): void { foreach ($model->getRules() as $rule) { - if (!in_array($model->getType(), $usedModels)) { + if (! in_array($model->getType(), $usedModels)) { continue; } if (\is_array($rule['type'])) { foreach ($rule['type'] as $ruleType) { - if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) { + if (! in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) { $usedModels[] = $ruleType; foreach ($this->models as $m) { if ($m->getType() === $ruleType) { $this->getNestedModels($m, $usedModels); + continue; } } } } } else { - if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) { + if (! in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) { $usedModels[] = $rule['type']; foreach ($this->models as $m) { if ($m->getType() === $rule['type']) { $this->getNestedModels($m, $usedModels); + continue; } } @@ -124,7 +126,7 @@ class Swagger2 extends Format } $id = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; + $desc = (! empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null; $produces = $route->getLabel('sdk.response.type', null); $model = $route->getLabel('sdk.response.model', 'none'); $routeSecurity = $route->getLabel('sdk.auth', []); @@ -153,7 +155,7 @@ class Swagger2 extends Format $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), + 'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id), 'consumes' => [], 'produces' => [], 'tags' => [$route->getLabel('sdk.namespace', 'default')], @@ -164,8 +166,8 @@ class Swagger2 extends Format 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), 'type' => $route->getLabel('sdk.methodType', ''), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($id) . '.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), + 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master'.$route->getLabel('sdk.description', ''), 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), @@ -193,8 +195,8 @@ class Swagger2 extends Format } } - if (!(\is_array($model)) && $model->isNone()) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ + if (! (\is_array($model)) && $model->isNone()) { + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ 'description' => in_array($produces, [ 'image/*', 'image/jpeg', @@ -206,42 +208,42 @@ class Swagger2 extends Format 'image/bmp', ]) ? 'Image' : 'File', 'schema' => [ - 'type' => 'file' + 'type' => 'file', ], ]; } else { if (\is_array($model)) { - $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + $modelDescription = \implode(', or ', \array_map(fn ($m) => $m->getName(), $model)); // model has multiple possible responses, we will use oneOf foreach ($model as $m) { $usedModels[] = $m->getType(); } - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ 'description' => $modelDescription, 'schema' => [ 'x-oneOf' => \array_map(function ($m) { - return ['$ref' => '#/definitions/' . $m->getType()]; - }, $model) + return ['$ref' => '#/definitions/'.$m->getType()]; + }, $model), ], ]; } else { // Response definition using one type $usedModels[] = $model->getType(); - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'schema' => [ - '$ref' => '#/definitions/' . $model->getType(), + '$ref' => '#/definitions/'.$model->getType(), ], ]; } } if (in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); + $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; + unset($temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['schema']); } - if ((!empty($scope))) { // && 'public' != $scope + if ((! empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; foreach ($route->getLabel('sdk.auth', []) as $security) { @@ -277,7 +279,7 @@ class Swagger2 extends Format $node = [ 'name' => $name, 'description' => $param['description'], - 'required' => !$param['optional'], + 'required' => ! $param['optional'], ]; foreach ($this->services as $service) { @@ -293,11 +295,10 @@ class Swagger2 extends Format $validator = $validator->getValidator(); } - - switch ((!empty($validator)) ? \get_class($validator) : '') { + switch ((! empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['type'] = $validator->getType(); - $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; + $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; break; case 'Utopia\Validator\Boolean': $node['type'] = $validator->getType(); @@ -308,11 +309,11 @@ class Swagger2 extends Format $node['x-upload-id'] = true; } $node['type'] = $validator->getType(); - $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; + $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; break; case 'Utopia\Database\Validator\UID': $node['type'] = $validator->getType(); - $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; + $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; break; case 'Utopia\Database\Validator\DatetimeValidator': $node['type'] = $validator->getType(); @@ -369,7 +370,7 @@ class Swagger2 extends Format $node['items'] = [ 'type' => 'string', ]; - $node['x-example'] = '["' . Permission::read(Role::any()) . '"]'; + $node['x-example'] = '["'.Permission::read(Role::any()).'"]'; break; case 'Utopia\Database\Validator\Roles': $node['type'] = $validator->getType(); @@ -377,7 +378,7 @@ class Swagger2 extends Format $node['items'] = [ 'type' => 'string', ]; - $node['x-example'] = '["' . Role::any()->toString() . '"]'; + $node['x-example'] = '["'.Role::any()->toString().'"]'; break; case 'Appwrite\Auth\Validator\Password': $node['type'] = $validator->getType(); @@ -442,11 +443,11 @@ class Swagger2 extends Format break; } - if ($param['optional'] && !\is_null($param['default'])) { // Param has default value + if ($param['optional'] && ! \is_null($param['default'])) { // Param has default value $node['default'] = $param['default']; } - if (false !== \strpos($url, ':' . $name)) { // Param is in URL path + if (false !== \strpos($url, ':'.$name)) { // Param is in URL path $node['in'] = 'path'; $temp['parameters'][] = $node; } elseif ($route->getMethod() == 'GET') { // Param is in query @@ -460,7 +461,7 @@ class Swagger2 extends Format continue; } - if (!$param['optional']) { + if (! $param['optional']) { $bodyRequired[] = $name; } @@ -491,14 +492,14 @@ class Swagger2 extends Format } } - $url = \str_replace(':' . $name, '{' . $name . '}', $url); + $url = \str_replace(':'.$name, '{'.$name.'}', $url); } - if (!empty($bodyRequired)) { + if (! empty($bodyRequired)) { $body['schema']['required'] = $bodyRequired; } - if (!empty($body['schema']['properties'])) { + if (! empty($body['schema']['properties'])) { $temp['parameters'][] = $body; } @@ -512,7 +513,7 @@ class Swagger2 extends Format } foreach ($this->models as $model) { - if (!in_array($model->getType(), $usedModels)) { + if (! in_array($model->getType(), $usedModels)) { continue; } @@ -524,7 +525,7 @@ class Swagger2 extends Format 'type' => 'object', ]; - if (!empty($rules)) { + if (! empty($rules)) { $output['definitions'][$model->getType()]['properties'] = []; } @@ -532,7 +533,7 @@ class Swagger2 extends Format $output['definitions'][$model->getType()]['additionalProperties'] = true; } - if (!empty($required)) { + if (! empty($required)) { $output['definitions'][$model->getType()]['required'] = $required; } @@ -577,17 +578,17 @@ class Swagger2 extends Format if (\is_array($rule['type'])) { if ($rule['array']) { $items = [ - 'x-anyOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type']) + 'x-anyOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/'.$type], $rule['type']), ]; } else { $items = [ - 'x-oneOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type']) + 'x-oneOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/'.$type], $rule['type']), ]; } } else { $items = [ 'type' => $type, - '$ref' => '#/definitions/' . $rule['type'], + '$ref' => '#/definitions/'.$rule['type'], ]; } break; @@ -600,6 +601,7 @@ class Swagger2 extends Format 'description' => $rule['description'] ?? '', 'x-example' => $rule['example'] ?? null, ]; + continue; } @@ -630,7 +632,7 @@ class Swagger2 extends Format if ($items) { $output['definitions'][$model->getType()]['properties'][$name]['items'] = $items; } - if (!in_array($name, $required)) { + if (! in_array($name, $required)) { $output['definitions'][$model->getType()]['properties'][$name]['x-nullable'] = true; } } diff --git a/src/Appwrite/Task/Validator/Cron.php b/src/Appwrite/Task/Validator/Cron.php index 03bd1c5220..a2709bc1c0 100644 --- a/src/Appwrite/Task/Validator/Cron.php +++ b/src/Appwrite/Task/Validator/Cron.php @@ -24,8 +24,7 @@ class Cron extends Validator * * Returns true if valid or false if not. * - * @param mixed $value - * + * @param mixed $value * @return bool */ public function isValid($value): bool @@ -34,7 +33,7 @@ class Cron extends Validator return true; } - if (!CronExpression::isValidExpression($value)) { + if (! CronExpression::isValidExpression($value)) { return false; } diff --git a/src/Appwrite/Template/Template.php b/src/Appwrite/Template/Template.php index c01d54389b..6b2bec0aef 100644 --- a/src/Appwrite/Template/Template.php +++ b/src/Appwrite/Template/Template.php @@ -17,18 +17,17 @@ class Template extends View * * Creates a new Template() from the file at $path * - * @param string $path - * + * @param string $path * @return self - * */ public static function fromFile(string $path): self { - if (!\is_readable($path)) { + if (! \is_readable($path)) { throw new Exception("$path view template is not readable."); } $template = new Template(); + return $template->setPath($path); } @@ -37,10 +36,8 @@ class Template extends View * * Creates a new Template() using a raw string * - * @param string $content - * + * @param string $content * @return self - * */ public static function fromString(string $content): self { @@ -50,6 +47,7 @@ class Template extends View $template = new Template(); $template->content = $content; + return $template; } @@ -71,10 +69,10 @@ class Template extends View if (\is_readable($this->path)) { $template = \file_get_contents($this->path); // Include template file - } elseif (!empty($this->content)) { + } elseif (! empty($this->content)) { $template = $this->print($this->content, self::FILTER_NL2P); } else { - throw new Exception('"' . $this->path . '" template is not readable or not found'); + throw new Exception('"'.$this->path.'" template is not readable or not found'); } // First replace the variables inside the params. Then replace the variables in the template @@ -90,7 +88,6 @@ class Template extends View * Parse URL string to array * * @param $url - * * @return mixed On seriously malformed URLs, parse_url() may return FALSE. */ public static function parseURL($url) @@ -104,25 +101,24 @@ class Template extends View * Convert PHP array to query string * * @param $url - * * @return string */ public static function unParseURL(array $url) { - $scheme = isset($url['scheme']) ? $url['scheme'] . '://' : ''; + $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; $host = isset($url['host']) ? $url['host'] : ''; - $port = isset($url['port']) ? ':' . $url['port'] : ''; + $port = isset($url['port']) ? ':'.$url['port'] : ''; $user = isset($url['user']) ? $url['user'] : ''; - $pass = isset($url['pass']) ? ':' . $url['pass'] : ''; + $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; $path = isset($url['path']) ? $url['path'] : ''; - $query = isset($url['query']) && !empty($url['query']) ? '?' . $url['query'] : ''; + $query = isset($url['query']) && ! empty($url['query']) ? '?'.$url['query'] : ''; - $fragment = isset($url['fragment']) ? '#' . $url['fragment'] : ''; + $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; - return $scheme . $user . $pass . $host . $port . $path . $query . $fragment; + return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; } /** @@ -131,8 +127,7 @@ class Template extends View * Merge array of params to query string * * @param $query1 - * @param array $query2 - * + * @param array $query2 * @return string */ public static function mergeQuery($query1, array $query2) @@ -149,7 +144,7 @@ class Template extends View /** * From Camel Case * - * @var string $input + * @var string * * @return string */ @@ -167,7 +162,7 @@ class Template extends View /** * From Camel Case to Dash Case * - * @var string $input + * @var string * * @return string */ diff --git a/src/Appwrite/URL/URL.php b/src/Appwrite/URL/URL.php index 98250ab429..bfc6b8ee7d 100644 --- a/src/Appwrite/URL/URL.php +++ b/src/Appwrite/URL/URL.php @@ -9,8 +9,7 @@ class URL * * Take a URL string and split it to array parts * - * @param string $url - * + * @param string $url * @return array */ public static function parse(string $url): array @@ -34,46 +33,45 @@ class URL * * Take URL parts and combine them to a valid string * - * @param array $url - * @param array $ommit - * + * @param array $url + * @param array $ommit * @return string */ public static function unparse(array $url, array $ommit = []): string { if (isset($url['path']) && \mb_substr($url['path'], 0, 1) !== '/') { - $url['path'] = '/' . $url['path']; + $url['path'] = '/'.$url['path']; } $parts = []; - $parts['scheme'] = isset($url['scheme']) ? $url['scheme'] . '://' : ''; + $parts['scheme'] = isset($url['scheme']) ? $url['scheme'].'://' : ''; $parts['host'] = isset($url['host']) ? $url['host'] : ''; - $parts['port'] = isset($url['port']) ? ':' . $url['port'] : ''; + $parts['port'] = isset($url['port']) ? ':'.$url['port'] : ''; $parts['user'] = isset($url['user']) ? $url['user'] : ''; - $parts['pass'] = isset($url['pass']) ? ':' . $url['pass'] : ''; + $parts['pass'] = isset($url['pass']) ? ':'.$url['pass'] : ''; - $parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'] . '@' : ''; + $parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'].'@' : ''; $parts['path'] = isset($url['path']) ? $url['path'] : ''; - $parts['query'] = isset($url['query']) && !empty($url['query']) ? '?' . $url['query'] : ''; + $parts['query'] = isset($url['query']) && ! empty($url['query']) ? '?'.$url['query'] : ''; - $parts['fragment'] = isset($url['fragment']) ? '#' . $url['fragment'] : ''; + $parts['fragment'] = isset($url['fragment']) ? '#'.$url['fragment'] : ''; if ($ommit) { foreach ($ommit as $key) { - if (isset($parts[ $key ])) { - $parts[ $key ] = ''; + if (isset($parts[$key])) { + $parts[$key] = ''; } } } - return $parts['scheme'] . $parts['user'] . $parts['pass'] . $parts['host'] . $parts['port'] . $parts['path'] . $parts['query'] . $parts['fragment']; + return $parts['scheme'].$parts['user'].$parts['pass'].$parts['host'].$parts['port'].$parts['path'].$parts['query'].$parts['fragment']; } /** @@ -81,8 +79,7 @@ class URL * * Convert query string to array * - * @param string $query - * + * @param string $query * @return array */ public static function parseQuery(string $query): array @@ -97,8 +94,7 @@ class URL * * Convert query string array to string * - * @param array $query - * + * @param array $query * @return string */ public static function unparseQuery(array $query): string diff --git a/src/Appwrite/Utopia/Database/Validator/CustomId.php b/src/Appwrite/Utopia/Database/Validator/CustomId.php index 90d550371b..b6e913cb46 100644 --- a/src/Appwrite/Utopia/Database/Validator/CustomId.php +++ b/src/Appwrite/Utopia/Database/Validator/CustomId.php @@ -12,12 +12,10 @@ class CustomId extends Key * Returns true if valid or false if not. * * @param $value - * * @return bool */ public function isValid($value): bool { - return $value == 'unique()' || parent::isValid($value); } } diff --git a/src/Appwrite/Utopia/Database/Validator/ProjectId.php b/src/Appwrite/Utopia/Database/Validator/ProjectId.php index 46b0cdf53e..482a74fc57 100644 --- a/src/Appwrite/Utopia/Database/Validator/ProjectId.php +++ b/src/Appwrite/Utopia/Database/Validator/ProjectId.php @@ -12,7 +12,6 @@ class ProjectId extends Validator * Returns true if valid or false if not. * * @param $value - * * @return bool */ public function isValid($value): bool diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 1463316ad1..86264df395 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -2,8 +2,6 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Select; - class Attributes extends Base { public const ALLOWED_ATTRIBUTES = [ @@ -13,12 +11,11 @@ class Attributes extends Base 'required', 'array', 'status', - 'error' + 'error', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 3eea7b7b7e..eca03206f9 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -2,24 +2,24 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Extend\Exception; -use Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; -use Utopia\Database\Validator\Query\Cursor; -use Utopia\Database\Validator\Query\Filter; -use Utopia\Database\Validator\Query\Order; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\Query\Filter; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; +use Utopia\Database\Validator\Query\Order; class Base extends Queries { /** * Expression constructor * - * @param string $collection - * @param string[] $allowedAttributes + * @param string $collection + * @param string[] $allowedAttributes + * * @throws \Exception */ public function __construct(string $collection, array $allowedAttributes) @@ -36,7 +36,7 @@ class Base extends Queries $attributes = []; foreach ($collection['attributes'] as $attribute) { $key = $attribute['$id']; - if (!isset($allowedAttributesLookup[$key])) { + if (! isset($allowedAttributesLookup[$key])) { continue; } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index c4d187520f..91d467b203 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -10,12 +10,11 @@ class Buckets extends Base 'fileSecurity', 'maximumFileSize', 'encryption', - 'antivirus' + 'antivirus', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php index 6e8fcb8339..9bf2381ed2 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php @@ -7,12 +7,11 @@ class Collections extends Base public const ALLOWED_ATTRIBUTES = [ 'name', 'enabled', - 'documentSecurity' + 'documentSecurity', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php index 22f7ad9b82..e47d9020d1 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php @@ -5,12 +5,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Databases extends Base { public const ALLOWED_ATTRIBUTES = [ - 'name' + 'name', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index 05b3326af1..20fe9a7123 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -13,7 +13,6 @@ class Deployments extends Base /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php index 2bfe46e28d..ca74367164 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php @@ -8,12 +8,11 @@ class Executions extends Base 'trigger', 'status', 'statusCode', - 'duration' + 'duration', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php index 1941eabcdb..5984d32b9c 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php @@ -10,12 +10,11 @@ class Files extends Base 'mimeType', 'sizeOriginal', 'chunksTotal', - 'chunksUploaded' + 'chunksUploaded', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php index a2ba368953..77b7e14028 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php @@ -12,12 +12,11 @@ class Functions extends Base 'schedule', 'scheduleNext', 'schedulePrevious', - 'timeout' + 'timeout', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php b/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php index cb0462ee13..346c2f4799 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php @@ -14,7 +14,6 @@ class Identities extends Base /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php index d9290e5737..6ebf3cf50f 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php @@ -14,7 +14,6 @@ class Indexes extends Base /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php index 5ff0098662..73add15ac4 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php @@ -9,12 +9,11 @@ class Memberships extends Base 'teamId', 'invited', 'joined', - 'confirm' + 'confirm', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php b/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php index 6b9e9e6d32..3cada3f633 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php @@ -11,12 +11,11 @@ class Migrations extends Base 'resources', 'statusCounters', 'resourceData', - 'errors' + 'errors', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php b/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php index 7fff26db7f..6f36d73660 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php @@ -2,18 +2,15 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Base; - class Projects extends Base { public const ALLOWED_ATTRIBUTES = [ 'name', - 'teamId' + 'teamId', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php index 83dbf665f1..00beab4e1d 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php @@ -12,7 +12,6 @@ class Providers extends Base /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php index 67aba71598..ccc5fdbf7c 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php @@ -6,12 +6,11 @@ class Teams extends Base { public const ALLOWED_ATTRIBUTES = [ 'name', - 'total' + 'total', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php index 9b0dfe61e6..b0fe844017 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php @@ -12,12 +12,11 @@ class Users extends Base 'passwordUpdate', 'registration', 'emailVerification', - 'phoneVerification' + 'phoneVerification', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php b/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php index eff7007c58..978c763b84 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php @@ -2,17 +2,14 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Base; - class Variables extends Base { public const ALLOWED_ATTRIBUTES = [ - 'key' + 'key', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 229c9dd53d..3f4d368e78 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -10,6 +10,7 @@ use Utopia\Swoole\Request as UtopiaRequest; class Request extends UtopiaRequest { private static ?Filter $filter = null; + private static ?Route $route = null; public function __construct(SwooleRequest $request) @@ -18,14 +19,14 @@ class Request extends UtopiaRequest } /** - * @inheritdoc + * {@inheritdoc} */ public function getParams(): array { $parameters = parent::getParams(); if (self::hasFilter() && self::hasRoute()) { - $endpointIdentifier = self::getRoute()->getLabel('sdk.namespace', 'unknown') . '.' . self::getRoute()->getLabel('sdk.method', 'unknown'); + $endpointIdentifier = self::getRoute()->getLabel('sdk.namespace', 'unknown').'.'.self::getRoute()->getLabel('sdk.method', 'unknown'); $parameters = self::getFilter()->parse($parameters, $endpointIdentifier); } @@ -35,8 +36,7 @@ class Request extends UtopiaRequest /** * Function to set a response filter * - * @param Filter|null $filter Filter the response filter to set - * + * @param Filter|null $filter Filter the response filter to set * @return void */ public static function setFilter(?Filter $filter): void @@ -67,8 +67,7 @@ class Request extends UtopiaRequest /** * Function to set a request route * - * @param Route|null $route the request route to set - * + * @param Route|null $route the request route to set * @return void */ public static function setRoute(?Route $route): void diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 59346c7e17..4c1ea1bfd1 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -7,9 +7,8 @@ abstract class Filter /** * Parse params to another format. * - * @param array $content - * @param string $model - * + * @param array $content + * @param string $model * @return array */ abstract public function parse(array $content, string $model): array; diff --git a/src/Appwrite/Utopia/Request/Filters/V12.php b/src/Appwrite/Utopia/Request/Filters/V12.php index f2a65307ae..96fbf62885 100644 --- a/src/Appwrite/Utopia/Request/Filters/V12.php +++ b/src/Appwrite/Utopia/Request/Filters/V12.php @@ -11,44 +11,44 @@ class V12 extends Filter { switch ($model) { // No IDs -> Custom IDs - case "account.create": - case "account.createMagicURLSession": - case "users.create": + case 'account.create': + case 'account.createMagicURLSession': + case 'users.create': $content = $this->addId($content, 'userId'); break; - case "functions.create": + case 'functions.create': $content = $this->addId($content, 'functionId'); break; - case "teams.create": + case 'teams.create': $content = $this->addId($content, 'teamId'); break; - // Status integer -> boolean - case "users.updateStatus": + // Status integer -> boolean + case 'users.updateStatus': $content = $this->convertStatus($content); break; - // Deprecating order type - case "functions.listExecutions": + // Deprecating order type + case 'functions.listExecutions': $content = $this->removeOrderType($content); break; - // The rest (more complex) formats - case "database.createDocument": + // The rest (more complex) formats + case 'database.createDocument': $content = $this->addId($content, 'documentId'); $content = $this->removeParentProperties($content); break; - case "database.listDocuments": + case 'database.listDocuments': $content = $this->removeOrderCast($content); $content = $this->convertOrder($content); $content = $this->convertQueries($content); break; - case "database.createCollection": + case 'database.createCollection': $content = $this->addId($content, 'collectionId'); $content = $this->removeRules($content); $content = $this->addCollectionPermissionLevel($content); break; - case "database.updateCollection": + case 'database.updateCollection': $content = $this->removeRules($content); $content = $this->addCollectionPermissionLevel($content); break; @@ -62,12 +62,14 @@ class V12 extends Filter protected function addId(array $content, string $key): array { $content[$key] = 'unique()'; + return $content; } protected function addCollectionPermissionLevel(array $content): array { $content['permission'] = 'document'; + return $content; } @@ -76,18 +78,21 @@ class V12 extends Filter protected function removeRules(array $content): array { unset($content['rules']); + return $content; } protected function removeOrderType(array $content): array { unset($content['orderType']); + return $content; } protected function removeOrderCast(array $content): array { unset($content['orderCast']); + return $content; } @@ -102,6 +107,7 @@ class V12 extends Filter if (isset($content['parentPropertyType'])) { unset($content['parentPropertyType']); } + return $content; } @@ -112,18 +118,19 @@ class V12 extends Filter if (isset($content['status'])) { $content['status'] = $content['status'] === 2 ? false : true; } + return $content; } protected function convertOrder(array $content): array { if (isset($content['orderField'])) { - $content['orderAttributes'] = [ $content['orderField'] ]; + $content['orderAttributes'] = [$content['orderField']]; unset($content['orderField']); } if (isset($content['orderType'])) { - $content['orderTypes'] = [ $content['orderType'] ]; + $content['orderTypes'] = [$content['orderType']]; unset($content['orderType']); } @@ -134,7 +141,7 @@ class V12 extends Filter { $queries = []; - if (!empty($content['filters'])) { + if (! empty($content['filters'])) { foreach ($content['filters'] as $filter) { $operators = ['=' => 'equal', '!=' => 'notEqual', '>' => 'greater', '<' => 'lesser', '<=' => 'lesserEqual', '>=' => 'greaterEqual']; foreach ($operators as $operator => $operatorVerbose) { @@ -151,10 +158,10 @@ class V12 extends Filter // Let's keep it at true and false string, but without "" around // No action needed } else { - $filterValue = \is_numeric($filterValue) ? $filterValue : '"' . $filterValue . '"'; + $filterValue = \is_numeric($filterValue) ? $filterValue : '"'.$filterValue.'"'; } - $query = $attributeKey . '.' . $operators[$usedOperator] . '(' . $filterValue . ')'; + $query = $attributeKey.'.'.$operators[$usedOperator].'('.$filterValue.')'; \array_push($queries, $query); } } diff --git a/src/Appwrite/Utopia/Request/Filters/V13.php b/src/Appwrite/Utopia/Request/Filters/V13.php index e1122fdd71..3f297b5943 100644 --- a/src/Appwrite/Utopia/Request/Filters/V13.php +++ b/src/Appwrite/Utopia/Request/Filters/V13.php @@ -11,13 +11,13 @@ class V13 extends Filter { switch ($model) { // Replaced Types - case "database.createIntegerAttribute": - case "database.createFloatAttribute": - $content = $this->convertStringToNum($content, "min"); - $content = $this->convertStringToNum($content, "max"); - $content = $this->convertStringToNum($content, "default"); + case 'database.createIntegerAttribute': + case 'database.createFloatAttribute': + $content = $this->convertStringToNum($content, 'min'); + $content = $this->convertStringToNum($content, 'max'); + $content = $this->convertStringToNum($content, 'default'); break; - case "functions.createExecution": + case 'functions.createExecution': $content = $this->convertExecution($content); } @@ -26,13 +26,15 @@ class V13 extends Filter private function convertStringToNum($content, $value) { - $content[$value] = is_null($content[$value]) ? null : (int)$content[$value]; + $content[$value] = is_null($content[$value]) ? null : (int) $content[$value]; + return $content; } private function convertExecution($content) { $content['async'] = true; + return $content; } } diff --git a/src/Appwrite/Utopia/Request/Filters/V14.php b/src/Appwrite/Utopia/Request/Filters/V14.php index 7130307f0d..1b50404f82 100644 --- a/src/Appwrite/Utopia/Request/Filters/V14.php +++ b/src/Appwrite/Utopia/Request/Filters/V14.php @@ -2,8 +2,8 @@ namespace Appwrite\Utopia\Request\Filters; -use Appwrite\Utopia\Request\Filter; use Appwrite\Migration\Version\V13 as MigrationV13; +use Appwrite\Utopia\Request\Filter; class V14 extends Filter { @@ -11,10 +11,10 @@ class V14 extends Filter public function parse(array $content, string $model): array { switch ($model) { - case "functions.create": - case "functions.update": - case "projects.createWebhook": - case "projects.updateWebhook": + case 'functions.create': + case 'functions.update': + case 'projects.createWebhook': + case 'projects.updateWebhook': $content = $this->convertEvents($content); break; } @@ -27,7 +27,7 @@ class V14 extends Filter $migration = new MigrationV13(); $events = $content['events'] ?? []; - $content['events'] = $migration->migrateEvents($events); + $content['events'] = $migration->migrateEvents($events); return $content; } diff --git a/src/Appwrite/Utopia/Request/Filters/V15.php b/src/Appwrite/Utopia/Request/Filters/V15.php index 318096fe0d..d535777350 100644 --- a/src/Appwrite/Utopia/Request/Filters/V15.php +++ b/src/Appwrite/Utopia/Request/Filters/V15.php @@ -5,8 +5,8 @@ namespace Appwrite\Utopia\Request\Filters; use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Query; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; class V15 extends Filter { @@ -81,11 +81,11 @@ class V15 extends Filter protected function convertLimitAndOffset($content) { if (isset($content['limit'])) { - $content['queries'][] = 'limit(' . $content['limit'] . ')'; + $content['queries'][] = 'limit('.$content['limit'].')'; } if (isset($content['offset'])) { - $content['queries'][] = 'offset(' . $content['offset'] . ')'; + $content['queries'][] = 'offset('.$content['offset'].')'; } unset($content['limit']); @@ -100,9 +100,9 @@ class V15 extends Filter $cursorDirection = $content['cursorDirection'] ?? Database::CURSOR_AFTER; if ($cursorDirection === Database::CURSOR_BEFORE) { - $content['queries'][] = 'cursorBefore("' . $content["cursor"] . '")'; + $content['queries'][] = 'cursorBefore("'.$content['cursor'].'")'; } else { - $content['queries'][] = 'cursorAfter("' . $content["cursor"] . '")'; + $content['queries'][] = 'cursorAfter("'.$content['cursor'].'")'; } } @@ -133,9 +133,9 @@ class V15 extends Filter $attribute = $content['orderAttributes'][$i] ?? ''; if ($type === Database::ORDER_DESC) { - $content['queries'][] = 'orderDesc("' . $attribute . '")'; + $content['queries'][] = 'orderDesc("'.$attribute.'")'; } else { - $content['queries'][] = 'orderAsc("' . $attribute . '")'; + $content['queries'][] = 'orderAsc("'.$attribute.'")'; } } } @@ -194,7 +194,7 @@ class V15 extends Filter protected function convertFilters($content) { - if (!isset($content['queries'])) { + if (! isset($content['queries'])) { return $content; } @@ -214,18 +214,19 @@ class V15 extends Filter $parts = explode($middle, $query); if (count($parts) > 1) { $attribute = $parts[0]; - $value = rtrim($parts[1], ")"); - $content['queries'][$i] = $newOperation . '("' . $attribute . '", [' . $value . '])'; + $value = rtrim($parts[1], ')'); + $content['queries'][$i] = $newOperation.'("'.$attribute.'", ['.$value.'])'; } } } } + return $content; } protected function convertExecute($content) { - if (!isset($content['execute'])) { + if (! isset($content['execute'])) { return $content; } @@ -247,7 +248,7 @@ class V15 extends Filter protected function convertExpire($content) { - if (!isset($content['expire'])) { + if (! isset($content['expire'])) { return $content; } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 952226a8d9..2954fc9d0d 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -2,14 +2,6 @@ namespace Appwrite\Utopia; -use Appwrite\Utopia\Response\Model\Message; -use Appwrite\Utopia\Response\Model\Subscriber; -use Appwrite\Utopia\Response\Model\Topic; -use Exception; -use Swoole\Http\Request as SwooleRequest; -use Utopia\Swoole\Response as SwooleResponse; -use Swoole\Http\Response as SwooleHTTPResponse; -use Utopia\Database\Document; use Appwrite\Utopia\Response\Filter; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Account; @@ -20,70 +12,72 @@ use Appwrite\Utopia\Response\Model\AlgoPhpass; use Appwrite\Utopia\Response\Model\AlgoScrypt; use Appwrite\Utopia\Response\Model\AlgoScryptModified; use Appwrite\Utopia\Response\Model\AlgoSha; -use Appwrite\Utopia\Response\Model\None; use Appwrite\Utopia\Response\Model\Any; use Appwrite\Utopia\Response\Model\Attribute; -use Appwrite\Utopia\Response\Model\AttributeList; -use Appwrite\Utopia\Response\Model\AttributeString; -use Appwrite\Utopia\Response\Model\AttributeInteger; -use Appwrite\Utopia\Response\Model\AttributeFloat; use Appwrite\Utopia\Response\Model\AttributeBoolean; +use Appwrite\Utopia\Response\Model\AttributeDatetime; use Appwrite\Utopia\Response\Model\AttributeEmail; use Appwrite\Utopia\Response\Model\AttributeEnum; +use Appwrite\Utopia\Response\Model\AttributeFloat; +use Appwrite\Utopia\Response\Model\AttributeInteger; use Appwrite\Utopia\Response\Model\AttributeIP; -use Appwrite\Utopia\Response\Model\AttributeURL; -use Appwrite\Utopia\Response\Model\AttributeDatetime; +use Appwrite\Utopia\Response\Model\AttributeList; use Appwrite\Utopia\Response\Model\AttributeRelationship; +use Appwrite\Utopia\Response\Model\AttributeString; +use Appwrite\Utopia\Response\Model\AttributeURL; use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; +use Appwrite\Utopia\Response\Model\Bucket; +use Appwrite\Utopia\Response\Model\Build; use Appwrite\Utopia\Response\Model\Collection; -use Appwrite\Utopia\Response\Model\Database; +use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Continent; use Appwrite\Utopia\Response\Model\Country; use Appwrite\Utopia\Response\Model\Currency; +use Appwrite\Utopia\Response\Model\Database; +use Appwrite\Utopia\Response\Model\Deployment; use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Domain; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; -use Appwrite\Utopia\Response\Model\Build; use Appwrite\Utopia\Response\Model\File; -use Appwrite\Utopia\Response\Model\Bucket; -use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Func; -use Appwrite\Utopia\Response\Model\Identity; -use Appwrite\Utopia\Response\Model\Index; -use Appwrite\Utopia\Response\Model\JWT; -use Appwrite\Utopia\Response\Model\Key; -use Appwrite\Utopia\Response\Model\Language; -use Appwrite\Utopia\Response\Model\User; -use Appwrite\Utopia\Response\Model\Session; -use Appwrite\Utopia\Response\Model\Team; -use Appwrite\Utopia\Response\Model\Locale; -use Appwrite\Utopia\Response\Model\Log; -use Appwrite\Utopia\Response\Model\Membership; -use Appwrite\Utopia\Response\Model\Metric; -use Appwrite\Utopia\Response\Model\Permissions; -use Appwrite\Utopia\Response\Model\Phone; -use Appwrite\Utopia\Response\Model\Platform; -use Appwrite\Utopia\Response\Model\Project; -use Appwrite\Utopia\Response\Model\Rule; -use Appwrite\Utopia\Response\Model\Deployment; -use Appwrite\Utopia\Response\Model\TemplateEmail; -use Appwrite\Utopia\Response\Model\Token; -use Appwrite\Utopia\Response\Model\Webhook; -use Appwrite\Utopia\Response\Model\Preferences; use Appwrite\Utopia\Response\Model\HealthAntivirus; use Appwrite\Utopia\Response\Model\HealthQueue; use Appwrite\Utopia\Response\Model\HealthStatus; use Appwrite\Utopia\Response\Model\HealthTime; use Appwrite\Utopia\Response\Model\HealthVersion; +use Appwrite\Utopia\Response\Model\Identity; +use Appwrite\Utopia\Response\Model\Index; +use Appwrite\Utopia\Response\Model\JWT; +use Appwrite\Utopia\Response\Model\Key; +use Appwrite\Utopia\Response\Model\Language; +use Appwrite\Utopia\Response\Model\Locale; use Appwrite\Utopia\Response\Model\LocaleCode; -use Appwrite\Utopia\Response\Model\Mock; // Keep last +use Appwrite\Utopia\Response\Model\Log; +use Appwrite\Utopia\Response\Model\Membership; +use Appwrite\Utopia\Response\Model\Message; +use Appwrite\Utopia\Response\Model\Metric; +use Appwrite\Utopia\Response\Model\Migration; +use Appwrite\Utopia\Response\Model\MigrationFirebaseProject; +use Appwrite\Utopia\Response\Model\MigrationReport; +use Appwrite\Utopia\Response\Model\Mock; +use Appwrite\Utopia\Response\Model\None; +use Appwrite\Utopia\Response\Model\Phone; +use Appwrite\Utopia\Response\Model\Platform; +use Appwrite\Utopia\Response\Model\Preferences; +use Appwrite\Utopia\Response\Model\Project; use Appwrite\Utopia\Response\Model\Provider; use Appwrite\Utopia\Response\Model\Runtime; +use Appwrite\Utopia\Response\Model\Session; +use Appwrite\Utopia\Response\Model\Subscriber; use Appwrite\Utopia\Response\Model\Target; +use Appwrite\Utopia\Response\Model\Team; +use Appwrite\Utopia\Response\Model\TemplateEmail; use Appwrite\Utopia\Response\Model\TemplateSMS; +use Appwrite\Utopia\Response\Model\Token; // Keep last +use Appwrite\Utopia\Response\Model\Topic; use Appwrite\Utopia\Response\Model\UsageBuckets; use Appwrite\Utopia\Response\Model\UsageCollection; use Appwrite\Utopia\Response\Model\UsageDatabase; @@ -93,10 +87,13 @@ use Appwrite\Utopia\Response\Model\UsageFunctions; use Appwrite\Utopia\Response\Model\UsageProject; use Appwrite\Utopia\Response\Model\UsageStorage; use Appwrite\Utopia\Response\Model\UsageUsers; +use Appwrite\Utopia\Response\Model\User; use Appwrite\Utopia\Response\Model\Variable; -use Appwrite\Utopia\Response\Model\Migration; -use Appwrite\Utopia\Response\Model\MigrationFirebaseProject; -use Appwrite\Utopia\Response\Model\MigrationReport; +use Appwrite\Utopia\Response\Model\Webhook; +use Exception; +use Swoole\Http\Response as SwooleHTTPResponse; +use Utopia\Database\Document; +use Utopia\Swoole\Response as SwooleResponse; /** * @method int getStatusCode() @@ -106,152 +103,263 @@ class Response extends SwooleResponse { // General public const MODEL_NONE = 'none'; + public const MODEL_ANY = 'any'; + public const MODEL_LOG = 'log'; + public const MODEL_LOG_LIST = 'logList'; + public const MODEL_ERROR = 'error'; + public const MODEL_METRIC = 'metric'; + public const MODEL_METRIC_LIST = 'metricList'; + public const MODEL_ERROR_DEV = 'errorDev'; + public const MODEL_BASE_LIST = 'baseList'; + public const MODEL_USAGE_DATABASES = 'usageDatabases'; + public const MODEL_USAGE_DATABASE = 'usageDatabase'; + public const MODEL_USAGE_COLLECTION = 'usageCollection'; + public const MODEL_USAGE_USERS = 'usageUsers'; + public const MODEL_USAGE_BUCKETS = 'usageBuckets'; + public const MODEL_USAGE_STORAGE = 'usageStorage'; + public const MODEL_USAGE_FUNCTIONS = 'usageFunctions'; + public const MODEL_USAGE_FUNCTION = 'usageFunction'; + public const MODEL_USAGE_PROJECT = 'usageProject'; // Database public const MODEL_DATABASE = 'database'; + public const MODEL_DATABASE_LIST = 'databaseList'; + public const MODEL_COLLECTION = 'collection'; + public const MODEL_COLLECTION_LIST = 'collectionList'; + public const MODEL_INDEX = 'index'; + public const MODEL_INDEX_LIST = 'indexList'; + public const MODEL_DOCUMENT = 'document'; + public const MODEL_DOCUMENT_LIST = 'documentList'; // Database Attributes public const MODEL_ATTRIBUTE = 'attribute'; + public const MODEL_ATTRIBUTE_LIST = 'attributeList'; + public const MODEL_ATTRIBUTE_STRING = 'attributeString'; + public const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger'; + public const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat'; + public const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean'; + public const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail'; + public const MODEL_ATTRIBUTE_ENUM = 'attributeEnum'; + public const MODEL_ATTRIBUTE_IP = 'attributeIp'; + public const MODEL_ATTRIBUTE_URL = 'attributeUrl'; + public const MODEL_ATTRIBUTE_DATETIME = 'attributeDatetime'; + public const MODEL_ATTRIBUTE_RELATIONSHIP = 'attributeRelationship'; // Users public const MODEL_ACCOUNT = 'account'; + public const MODEL_USER = 'user'; + public const MODEL_USER_LIST = 'userList'; + public const MODEL_SESSION = 'session'; + public const MODEL_SESSION_LIST = 'sessionList'; + public const MODEL_IDENTITY = 'identity'; + public const MODEL_IDENTITY_LIST = 'identityList'; + public const MODEL_TOKEN = 'token'; + public const MODEL_JWT = 'jwt'; + public const MODEL_PREFERENCES = 'preferences'; // Users password algos public const MODEL_ALGO_MD5 = 'algoMd5'; + public const MODEL_ALGO_SHA = 'algoSha'; + public const MODEL_ALGO_SCRYPT = 'algoScrypt'; + public const MODEL_ALGO_SCRYPT_MODIFIED = 'algoScryptModified'; + public const MODEL_ALGO_BCRYPT = 'algoBcrypt'; + public const MODEL_ALGO_ARGON2 = 'algoArgon2'; + public const MODEL_ALGO_PHPASS = 'algoPhpass'; // Storage public const MODEL_FILE = 'file'; + public const MODEL_FILE_LIST = 'fileList'; + public const MODEL_BUCKET = 'bucket'; + public const MODEL_BUCKET_LIST = 'bucketList'; // Locale public const MODEL_LOCALE = 'locale'; + public const MODEL_LOCALE_CODE = 'localeCode'; + public const MODEL_LOCALE_CODE_LIST = 'localeCodeList'; + public const MODEL_COUNTRY = 'country'; + public const MODEL_COUNTRY_LIST = 'countryList'; + public const MODEL_CONTINENT = 'continent'; + public const MODEL_CONTINENT_LIST = 'continentList'; + public const MODEL_CURRENCY = 'currency'; + public const MODEL_CURRENCY_LIST = 'currencyList'; + public const MODEL_LANGUAGE = 'language'; + public const MODEL_LANGUAGE_LIST = 'languageList'; + public const MODEL_PHONE = 'phone'; + public const MODEL_PHONE_LIST = 'phoneList'; // Messaging public const MODEL_PROVIDER = 'provider'; + public const MODEL_PROVIDER_LIST = 'providerList'; + public const MODEL_MESSAGE = 'message'; + public const MODEL_MESSAGE_LIST = 'messageList'; + public const MODEL_TOPIC = 'topic'; + public const MODEL_TOPIC_LIST = 'topicList'; + public const MODEL_SUBSCRIBER = 'subscriber'; + public const MODEL_SUBSCRIBER_LIST = 'subscriberList'; + public const MODEL_TARGET = 'target'; + public const MODEL_TARGET_LIST = 'targetList'; // Teams public const MODEL_TEAM = 'team'; + public const MODEL_TEAM_LIST = 'teamList'; + public const MODEL_MEMBERSHIP = 'membership'; + public const MODEL_MEMBERSHIP_LIST = 'membershipList'; // Functions public const MODEL_FUNCTION = 'function'; + public const MODEL_FUNCTION_LIST = 'functionList'; + public const MODEL_RUNTIME = 'runtime'; + public const MODEL_RUNTIME_LIST = 'runtimeList'; + public const MODEL_DEPLOYMENT = 'deployment'; + public const MODEL_DEPLOYMENT_LIST = 'deploymentList'; + public const MODEL_EXECUTION = 'execution'; + public const MODEL_EXECUTION_LIST = 'executionList'; + public const MODEL_BUILD = 'build'; + public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet + public const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; // Migrations public const MODEL_MIGRATION = 'migration'; + public const MODEL_MIGRATION_LIST = 'migrationList'; + public const MODEL_MIGRATION_REPORT = 'migrationReport'; + public const MODEL_MIGRATION_FIREBASE_PROJECT = 'firebaseProject'; + public const MODEL_MIGRATION_FIREBASE_PROJECT_LIST = 'firebaseProjectList'; // Project public const MODEL_PROJECT = 'project'; + public const MODEL_PROJECT_LIST = 'projectList'; + public const MODEL_WEBHOOK = 'webhook'; + public const MODEL_WEBHOOK_LIST = 'webhookList'; + public const MODEL_KEY = 'key'; + public const MODEL_KEY_LIST = 'keyList'; + public const MODEL_AUTH_PROVIDER = 'authProvider'; + public const MODEL_AUTH_PROVIDER_LIST = 'authProviderList'; + public const MODEL_PLATFORM = 'platform'; + public const MODEL_PLATFORM_LIST = 'platformList'; + public const MODEL_DOMAIN = 'domain'; + public const MODEL_DOMAIN_LIST = 'domainList'; + public const MODEL_VARIABLE = 'variable'; + public const MODEL_VARIABLE_LIST = 'variableList'; + public const MODEL_SMS_TEMPLATE = 'smsTemplate'; + public const MODEL_EMAIL_TEMPLATE = 'emailTemplate'; // Health public const MODEL_HEALTH_STATUS = 'healthStatus'; + public const MODEL_HEALTH_VERSION = 'healthVersion'; + public const MODEL_HEALTH_QUEUE = 'healthQueue'; + public const MODEL_HEALTH_TIME = 'healthTime'; + public const MODEL_HEALTH_ANTIVIRUS = 'healthAntivirus'; + public const MODEL_HEALTH_STATUS_LIST = 'healthStatusList'; // Console @@ -259,7 +367,9 @@ class Response extends SwooleResponse // Deprecated public const MODEL_PERMISSIONS = 'permissions'; + public const MODEL_RULE = 'rule'; + public const MODEL_TASK = 'task'; // Tests (keep last) @@ -278,7 +388,7 @@ class Response extends SwooleResponse /** * Response constructor. * - * @param float $time + * @param float $time */ public function __construct(SwooleHTTPResponse $response) { @@ -421,6 +531,7 @@ class Response extends SwooleResponse * HTTP content types */ public const CONTENT_TYPE_YAML = 'application/x-yaml'; + public const CONTENT_TYPE_NULL = 'null'; /** @@ -443,14 +554,15 @@ class Response extends SwooleResponse /** * Get Model Object * - * @param string $key + * @param string $key * @return Model + * * @throws Exception */ public function getModel(string $key): Model { - if (!isset($this->models[$key])) { - throw new Exception('Undefined model: ' . $key); + if (! isset($this->models[$key])) { + throw new Exception('Undefined model: '.$key); } return $this->models[$key]; @@ -470,10 +582,11 @@ class Response extends SwooleResponse * Validate response objects and outputs * the response according to given format type * - * @param Document $document - * @param string $model + * @param Document $document + * @param string $model * * return void + * * @throws Exception */ public function dynamic(Document $document, string $model): void @@ -487,11 +600,11 @@ class Response extends SwooleResponse switch ($this->getContentType()) { case self::CONTENT_TYPE_JSON: - $this->json(!empty($output) ? $output : new \stdClass()); + $this->json(! empty($output) ? $output : new \stdClass()); break; case self::CONTENT_TYPE_YAML: - $this->yaml(!empty($output) ? $output : new \stdClass()); + $this->yaml(! empty($output) ? $output : new \stdClass()); break; case self::CONTENT_TYPE_NULL: @@ -501,7 +614,7 @@ class Response extends SwooleResponse if ($model === self::MODEL_NONE) { $this->noContent(); } else { - $this->json(!empty($output) ? $output : new \stdClass()); + $this->json(! empty($output) ? $output : new \stdClass()); } break; } @@ -510,18 +623,19 @@ class Response extends SwooleResponse /** * Generate valid response object from document data * - * @param Document $document - * @param string $model + * @param Document $document + * @param string $model * * return array * @return array + * * @throws Exception */ public function output(Document $document, string $model): array { - $data = new Document($document->getArrayCopy()); - $model = $this->getModel($model); - $output = []; + $data = new Document($document->getArrayCopy()); + $model = $this->getModel($model); + $output = []; $data = $model->filter($document); @@ -532,17 +646,17 @@ class Response extends SwooleResponse } foreach ($model->getRules() as $key => $rule) { - if (!$document->isSet($key) && $rule['required']) { // do not set attribute in response if not required + if (! $document->isSet($key) && $rule['required']) { // do not set attribute in response if not required if (\array_key_exists('default', $rule)) { $data->setAttribute($key, $rule['default']); } else { - throw new Exception('Model ' . $model->getName() . ' is missing response key: ' . $key); + throw new Exception('Model '.$model->getName().' is missing response key: '.$key); } } if ($rule['array']) { - if (!is_array($document[$key])) { - throw new Exception($key . ' must be an array of type ' . $rule['type']); + if (! is_array($document[$key])) { + throw new Exception($key.' must be an array of type '.$rule['type']); } foreach ($document[$key] as $index => $item) { @@ -552,7 +666,7 @@ class Response extends SwooleResponse $condition = false; foreach ($this->getModel($type)->conditions as $attribute => $val) { $condition = $item->getAttribute($attribute) === $val; - if (!$condition) { + if (! $condition) { break; } } @@ -565,8 +679,8 @@ class Response extends SwooleResponse $ruleType = $rule['type']; } - if (!array_key_exists($ruleType, $this->models)) { - throw new Exception('Missing model for rule: ' . $ruleType); + if (! array_key_exists($ruleType, $this->models)) { + throw new Exception('Missing model for rule: '.$ruleType); } $data[$key][$index] = $this->output($item, $ruleType); @@ -591,14 +705,13 @@ class Response extends SwooleResponse * * Generate HTTP response output including the response header (+cookies) and body and prints them. * - * @param string $body - * + * @param string $body * @return void */ public function file(string $body = ''): void { $this->payload = [ - 'payload' => $body + 'payload' => $body, ]; $this->send($body); @@ -612,14 +725,14 @@ class Response extends SwooleResponse * * @see https://en.wikipedia.org/wiki/YAML * - * @param array $data - * + * @param array $data * @return void + * * @throws Exception */ public function yaml(array $data): void { - if (!extension_loaded('yaml')) { + if (! extension_loaded('yaml')) { throw new Exception('Missing yaml extension. Learn more at: https://www.php.net/manual/en/book.yaml.php'); } @@ -640,7 +753,6 @@ class Response extends SwooleResponse * Function to set a response filter * * @param $filter the response filter to set - * * @return void */ public static function setFilter(?Filter $filter) diff --git a/src/Appwrite/Utopia/Response/Filter.php b/src/Appwrite/Utopia/Response/Filter.php index 9110abd07a..47cca955fe 100644 --- a/src/Appwrite/Utopia/Response/Filter.php +++ b/src/Appwrite/Utopia/Response/Filter.php @@ -7,9 +7,8 @@ abstract class Filter /** * Parse the content to another format. * - * @param array $content - * @param string $model - * + * @param array $content + * @param string $model * @return array */ abstract public function parse(array $content, string $model): array; diff --git a/src/Appwrite/Utopia/Response/Filters/V11.php b/src/Appwrite/Utopia/Response/Filters/V11.php index 8fa22f42b2..09f9fbfc06 100644 --- a/src/Appwrite/Utopia/Response/Filters/V11.php +++ b/src/Appwrite/Utopia/Response/Filters/V11.php @@ -42,7 +42,7 @@ class V11 extends Filter $parsedResponse = $this->parseFunctionsList($content); break; - // Convert status from boolean to int + // Convert status from boolean to int case Response::MODEL_USER: $parsedResponse = $this->parseStatus($content); break; @@ -50,7 +50,7 @@ class V11 extends Filter $parsedResponse = $this->parseUserList($content); break; - // Convert all Health responses back to original + // Convert all Health responses back to original case Response::MODEL_HEALTH_STATUS: $parsedResponse = $this->parseHealthStatus($content); break; @@ -67,7 +67,7 @@ class V11 extends Filter $parsedResponse = $this->parseHealthAntivirus($content); break; - // Complex filters + // Complex filters case Response::MODEL_COLLECTION: $parsedResponse = $this->parseCollection($content); break; @@ -101,6 +101,7 @@ class V11 extends Filter $parsedResponse[] = $this->parsePermissions($document); } $content['documents'] = $parsedResponse; + return $content; } @@ -112,6 +113,7 @@ class V11 extends Filter $parsedResponse[] = $this->parsePermissions($file); } $content['files'] = $parsedResponse; + return $content; } @@ -123,6 +125,7 @@ class V11 extends Filter $parsedResponse[] = $this->parseExecutionPermissions($execution); } $content['executions'] = $parsedResponse; + return $content; } @@ -134,6 +137,7 @@ class V11 extends Filter $parsedResponse[] = $this->parseFunctionPermissions($function); } $content['functions'] = $parsedResponse; + return $content; } @@ -145,6 +149,7 @@ class V11 extends Filter $parsedResponse[] = $this->parseStatus($user); } $content['users'] = $parsedResponse; + return $content; } @@ -159,6 +164,7 @@ class V11 extends Filter $parsedResponse = $this->addDate($content, 'dateCreated'); $parsedResponse = $this->addDate($content, 'dateUpdated'); $parsedResponse = $this->parseAttributes($content); + return $parsedResponse; } @@ -170,6 +176,7 @@ class V11 extends Filter $parsedResponse[] = $this->parseCollection($collection); } $content['collections'] = $parsedResponse; + return $content; } @@ -181,6 +188,7 @@ class V11 extends Filter $parsedResponse = $this->removeRule($content, 'userName'); $parsedResponse = $this->removeRule($content, 'mode'); $parsedResponse = $this->removeRule($content, 'sum'); + return $parsedResponse; } @@ -192,6 +200,7 @@ class V11 extends Filter $parsedResponse[] = $this->parseLog($log); } $content['logs'] = $parsedResponse; + return $content; } @@ -203,6 +212,7 @@ class V11 extends Filter $parsedResponse = $this->parseOAuths($content); $parsedResponse = $this->parseAuthsStatus($content); $parsedResponse = $this->removeServicesStatus($content); + return $parsedResponse; } @@ -214,6 +224,7 @@ class V11 extends Filter $parsedResponse[] = $this->parseProject($project); } $content['projects'] = $parsedResponse; + return $content; } @@ -248,7 +259,6 @@ class V11 extends Filter return $content; } - protected function parseHealthQueue(array $content) { // Did not change @@ -303,15 +313,15 @@ class V11 extends Filter protected function parseOAuths(array $content) { - $regexPattern = "/provider([a-zA-Z0-9]+)(Appid|Secret)/"; + $regexPattern = '/provider([a-zA-Z0-9]+)(Appid|Secret)/'; foreach ($content as $key => $value) { \preg_match_all($regexPattern, $key, $regexGroups); if (\count($regexGroups[1]) > 0 && \count($regexGroups[2]) > 0) { $providerName = $regexGroups[1][0]; $valueKey = $regexGroups[2][0]; - $content['usersOauth2' . $providerName . $valueKey] = $value; - unset($content['provider' . $providerName . $valueKey]); + $content['usersOauth2'.$providerName.$valueKey] = $value; + unset($content['provider'.$providerName.$valueKey]); } } @@ -320,7 +330,7 @@ class V11 extends Filter protected function parseAuthsStatus(array $content) { - $regexPattern = "/auth([a-zA-Z0-9]+)/"; + $regexPattern = '/auth([a-zA-Z0-9]+)/'; foreach ($content as $key => $value) { \preg_match_all($regexPattern, $key, $regexGroups); @@ -328,7 +338,7 @@ class V11 extends Filter $providerName = $regexGroups[1][0]; $content[$providerName] = $value; - unset($content['auth' . $providerName]); + unset($content['auth'.$providerName]); } } @@ -377,15 +387,16 @@ class V11 extends Filter protected function parsePermissions(array $content) { - $content['$permissions'] = [ 'read' => $content['$read'], 'write' => $content['$write'] ]; + $content['$permissions'] = ['read' => $content['$read'], 'write' => $content['$write']]; unset($content['$read']); unset($content['$write']); + return $content; } protected function parseFunctionPermissions(array $content) { - $content['$permissions'] = [ 'execute' => $content['execute'] ]; + $content['$permissions'] = ['execute' => $content['execute']]; unset($content['execute']); return $content; @@ -393,7 +404,7 @@ class V11 extends Filter protected function parseExecutionPermissions(array $content) { - $content['$permissions'] = [ 'read' => $content['$read'] ]; + $content['$permissions'] = ['read' => $content['$read']]; unset($content['$read']); return $content; diff --git a/src/Appwrite/Utopia/Response/Filters/V12.php b/src/Appwrite/Utopia/Response/Filters/V12.php index 79d22ad044..795135bf43 100644 --- a/src/Appwrite/Utopia/Response/Filters/V12.php +++ b/src/Appwrite/Utopia/Response/Filters/V12.php @@ -99,6 +99,7 @@ class V12 extends Filter protected function parseError(array $content) { unset($content['type']); + return $content; } @@ -124,6 +125,7 @@ class V12 extends Filter $content['sessions'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); + return $content; } @@ -146,6 +148,7 @@ class V12 extends Filter $content['files'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); + return $content; } @@ -153,6 +156,7 @@ class V12 extends Filter { $content['tag'] = $content['deployment']; unset($content['deployment']); + return $content; } @@ -166,6 +170,7 @@ class V12 extends Filter $content['functions'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); + return $content; } @@ -173,6 +178,7 @@ class V12 extends Filter { $content['functionId'] = $content['resourceId']; $content['command'] = $content['entrypoint']; + return $content; } @@ -186,12 +192,14 @@ class V12 extends Filter $content['deployments'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); + return $content; } protected function parseUsageBuckets(array $content) { unset($content['filesStorage']); + return $content; } @@ -237,6 +245,7 @@ class V12 extends Filter $content['executions'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); + return $content; } @@ -244,6 +253,7 @@ class V12 extends Filter { $content['sum'] = $content['total']; unset($content['total']); + return $content; } @@ -257,6 +267,7 @@ class V12 extends Filter $content['teams'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); + return $content; } @@ -264,6 +275,7 @@ class V12 extends Filter { $content['sum'] = $content['total']; unset($content['total']); + return $content; } } diff --git a/src/Appwrite/Utopia/Response/Filters/V13.php b/src/Appwrite/Utopia/Response/Filters/V13.php index d48473593e..2c613280ac 100644 --- a/src/Appwrite/Utopia/Response/Filters/V13.php +++ b/src/Appwrite/Utopia/Response/Filters/V13.php @@ -55,6 +55,7 @@ class V13 extends Filter $parsedResponse[] = $this->parseExecution($document); } $content['executions'] = $parsedResponse; + return $content; } @@ -74,6 +75,7 @@ class V13 extends Filter $parsedResponse[] = $this->parseProject($document); } $content['projects'] = $parsedResponse; + return $content; } @@ -98,6 +100,7 @@ class V13 extends Filter $parsedResponse[] = $this->parseMembership($document); } $content['memberships'] = $parsedResponse; + return $content; } } diff --git a/src/Appwrite/Utopia/Response/Filters/V15.php b/src/Appwrite/Utopia/Response/Filters/V15.php index 232feec201..fadf426f1d 100644 --- a/src/Appwrite/Utopia/Response/Filters/V15.php +++ b/src/Appwrite/Utopia/Response/Filters/V15.php @@ -210,11 +210,13 @@ class V15 extends Filter if (array_key_exists($attribute, $content)) { if (empty($content[$attribute])) { $content[$attribute] = 0; + continue; } $content[$attribute] = strtotime($content[$attribute]); } } + return $content; } @@ -225,18 +227,20 @@ class V15 extends Filter unset($content['hashOptions']); $content = $this->parseDatetimeAttributes($content, ['registration', 'passwordUpdate', '$createdAt', '$updatedAt']); + return $content; } protected function parseMetric(array $content) { $content = $this->parseDatetimeAttributes($content, ['date']); + return $content; } protected function parsePermissions(array $content) { - if (!isset($content['$permissions'])) { + if (! isset($content['$permissions'])) { return $content; } @@ -248,10 +252,10 @@ class V15 extends Filter $permission = Permission::parse($permission); $permission_value = $permission->getRole(); if ($permission->getIdentifier()) { - $permission_value .= ':' . $permission->getIdentifier(); + $permission_value .= ':'.$permission->getIdentifier(); } if ($permission->getDimension()) { - $permission_value .= '/' . $permission->getDimension(); + $permission_value .= '/'.$permission->getDimension(); } // Old type permissions meant that 'write' is equivalent to 'create', 'update' and 'delete' @@ -305,6 +309,7 @@ class V15 extends Filter unset($content['documentSecurity']); $content = $this->parsePermissions($content); $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + return $content; } @@ -312,6 +317,7 @@ class V15 extends Filter { $content = $this->parsePermissions($content); $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + return $content; } @@ -325,6 +331,7 @@ class V15 extends Filter unset($content['$databaseId']); $content = $this->parsePermissionsCreatedAtUpdatedAt($content); + return $content; } @@ -354,6 +361,7 @@ class V15 extends Filter private function parseCreatedAtUpdatedAt($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + return $content; } @@ -386,24 +394,28 @@ class V15 extends Filter private function parseKey($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'expire']); + return $content; } private function parseLog($content) { $content = $this->parseDatetimeAttributes($content, ['time']); + return $content; } private function parseMembership($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'invited', 'joined']); + return $content; } private function parseSession($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', 'expire', 'providerAccessTokenExpiry']); + return $content; } diff --git a/src/Appwrite/Utopia/Response/Model.php b/src/Appwrite/Utopia/Response/Model.php index 8a0bb78cba..4aa4189248 100644 --- a/src/Appwrite/Utopia/Response/Model.php +++ b/src/Appwrite/Utopia/Response/Model.php @@ -7,12 +7,19 @@ use Utopia\Database\Document; abstract class Model { public const TYPE_STRING = 'string'; + public const TYPE_INTEGER = 'integer'; + public const TYPE_FLOAT = 'double'; + public const TYPE_BOOLEAN = 'boolean'; + public const TYPE_JSON = 'json'; + public const TYPE_DATETIME = 'datetime'; + public const TYPE_DATETIME_EXAMPLE = '2020-10-15T06:38:00.000+00:00'; + public const TYPE_RELATIONSHIP = 'relationship'; /** @@ -40,7 +47,6 @@ abstract class Model */ public array $conditions = []; - /** * Filter Document Structure * @@ -79,8 +85,8 @@ abstract class Model * Add a New Rule * If rule is an array of documents with varying models * - * @param string $key - * @param array $options + * @param string $key + * @param array $options * @return Model */ protected function addRule(string $key, array $options): self @@ -89,7 +95,7 @@ abstract class Model 'required' => true, 'array' => false, 'description' => '', - 'example' => '' + 'example' => '', ], $options); return $this; @@ -99,7 +105,7 @@ abstract class Model * Delete an existing Rule * If rule exists, it will be removed * - * @param string $key + * @param string $key * @return Model */ protected function removeRule(string $key): self diff --git a/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php b/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php index 3e162bb905..ff2b0f94e0 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php @@ -34,8 +34,7 @@ class AlgoArgon2 extends Model 'description' => 'Number of threads used to compute hash.', 'default' => '', 'example' => 3, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php b/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php index 4dda297d71..066f976433 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php @@ -39,8 +39,7 @@ class AlgoScrypt extends Model 'description' => 'Length used to compute hash.', 'default' => 64, 'example' => 64, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php b/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php index 40b9df1dad..73104eba7a 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php @@ -33,8 +33,7 @@ class AlgoScryptModified extends Model 'description' => 'Key used to compute hash.', 'default' => '', 'example' => 'XyEKE9RcTDeLEsL/RjwPDBv/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Attribute.php b/src/Appwrite/Utopia/Response/Model/Attribute.php index 9f9ceca317..c7a014bd32 100644 --- a/src/Appwrite/Utopia/Response/Model/Attribute.php +++ b/src/Appwrite/Utopia/Response/Model/Attribute.php @@ -46,8 +46,7 @@ class Attribute extends Model 'default' => false, 'required' => false, 'example' => false, - ]) - ; + ]); } public array $conditions = []; diff --git a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php index 05846817ca..e96140d0b3 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php @@ -28,13 +28,12 @@ class AttributeBoolean extends Attribute 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', 'default' => null, 'required' => false, - 'example' => false - ]) - ; + 'example' => false, + ]); } public array $conditions = [ - 'type' => self::TYPE_BOOLEAN + 'type' => self::TYPE_BOOLEAN, ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php b/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php index 4651aebd06..ccad8e7627 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php @@ -37,12 +37,11 @@ class AttributeDatetime extends Attribute 'example' => self::TYPE_DATETIME_EXAMPLE, 'array' => false, 'required' => false, - ]) - ; + ]); } public array $conditions = [ - 'type' => self::TYPE_DATETIME + 'type' => self::TYPE_DATETIME, ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php index 078087dd4b..ffcdbc6eb1 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php @@ -35,13 +35,12 @@ class AttributeEmail extends Attribute 'default' => null, 'required' => false, 'example' => 'default@example.com', - ]) - ; + ]); } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_EMAIL + 'format' => \APP_DATABASE_ATTRIBUTE_EMAIL, ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php index 992b62ee3a..0549c3cbe6 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php @@ -42,13 +42,12 @@ class AttributeEnum extends Attribute 'default' => null, 'required' => false, 'example' => 'element', - ]) - ; + ]); } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_ENUM + 'format' => \APP_DATABASE_ATTRIBUTE_ENUM, ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php index 266b89c330..28bd88e749 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php @@ -43,8 +43,7 @@ class AttributeFloat extends Attribute 'default' => null, 'required' => false, 'example' => 2.5, - ]) - ; + ]); } public array $conditions = [ diff --git a/src/Appwrite/Utopia/Response/Model/AttributeIP.php b/src/Appwrite/Utopia/Response/Model/AttributeIP.php index cfa309317a..2e746d735a 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeIP.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeIP.php @@ -35,13 +35,12 @@ class AttributeIP extends Attribute 'default' => null, 'required' => false, 'example' => '192.0.2.0', - ]) - ; + ]); } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_IP + 'format' => \APP_DATABASE_ATTRIBUTE_IP, ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php index fddfe57445..f672592553 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php @@ -43,8 +43,7 @@ class AttributeInteger extends Attribute 'default' => null, 'required' => false, 'example' => 10, - ]) - ; + ]); } public array $conditions = [ @@ -53,6 +52,7 @@ class AttributeInteger extends Attribute /** * Get Name * + * * @return string */ public function getName(): string diff --git a/src/Appwrite/Utopia/Response/Model/AttributeList.php b/src/Appwrite/Utopia/Response/Model/AttributeList.php index 8b04475a14..b093dd7fe9 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeList.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeList.php @@ -27,13 +27,12 @@ class AttributeList extends Model Response::MODEL_ATTRIBUTE_IP, Response::MODEL_ATTRIBUTE_DATETIME, Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute + Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute ], 'description' => 'List of attributes.', 'default' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php index d88fbd1530..73b6a566f2 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php @@ -47,8 +47,7 @@ class AttributeRelationship extends Attribute 'description' => 'Whether this is the parent or child side of the relationship', 'default' => '', 'example' => 'parent|child', - ]) - ; + ]); } public array $conditions = [ @@ -83,7 +82,7 @@ class AttributeRelationship extends Attribute public function filter(Document $document): Document { $options = $document->getAttribute('options'); - if (!\is_null($options)) { + if (! \is_null($options)) { $document->setAttribute('relatedCollection', $options['relatedCollection']); $document->setAttribute('relationType', $options['relationType']); $document->setAttribute('twoWay', $options['twoWay']); @@ -91,6 +90,7 @@ class AttributeRelationship extends Attribute $document->setAttribute('side', $options['side']); $document->setAttribute('onDelete', $options['onDelete']); } + return $document; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index 12bb42009d..eb72d705e6 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -23,8 +23,7 @@ class AttributeString extends Attribute 'default' => null, 'required' => false, 'example' => 'default', - ]) - ; + ]); } public array $conditions = [ diff --git a/src/Appwrite/Utopia/Response/Model/AttributeURL.php b/src/Appwrite/Utopia/Response/Model/AttributeURL.php index 633d5b49d7..78bd9c24d2 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeURL.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeURL.php @@ -35,13 +35,12 @@ class AttributeURL extends Attribute 'default' => null, 'required' => false, 'example' => 'http://example.com', - ]) - ; + ]); } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_URL + 'format' => \APP_DATABASE_ATTRIBUTE_URL, ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AuthProvider.php b/src/Appwrite/Utopia/Response/Model/AuthProvider.php index 0171a3c152..840a2aa661 100644 --- a/src/Appwrite/Utopia/Response/Model/AuthProvider.php +++ b/src/Appwrite/Utopia/Response/Model/AuthProvider.php @@ -43,8 +43,7 @@ class AuthProvider extends Model 'type' => self::TYPE_BOOLEAN, 'description' => 'Auth Provider is active and can be used to create session.', 'example' => '', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/BaseList.php b/src/Appwrite/Utopia/Response/Model/BaseList.php index 0c2cc072f3..cb0010a4e9 100644 --- a/src/Appwrite/Utopia/Response/Model/BaseList.php +++ b/src/Appwrite/Utopia/Response/Model/BaseList.php @@ -17,12 +17,12 @@ class BaseList extends Model protected string $type = ''; /** - * @param string $name - * @param string $type - * @param string $key - * @param string $model - * @param bool $paging - * @param bool $public + * @param string $name + * @param string $type + * @param string $key + * @param string $model + * @param bool $paging + * @param bool $public */ public function __construct(string $name, string $type, string $key, string $model, bool $paging = true, bool $public = true) { @@ -34,13 +34,13 @@ class BaseList extends Model $namesWithCap = [ 'documents', 'collections', 'users', 'files', 'buckets', 'functions', 'deployments', 'executions', 'projects', 'webhooks', 'keys', - 'platforms', 'domains', 'memberships', 'teams', 'targets' + 'platforms', 'domains', 'memberships', 'teams', 'targets', ]; if (\in_array($name, $namesWithCap)) { - $description = 'Total number of ' . $key . ' documents that matched your query used as reference for offset pagination. When the `total` number of ' . $key . ' documents available is greater than 5000, total returned will be capped at 5000, and cursor pagination should be used. Read more about [pagination](https://appwrite.io/docs/pagination).'; + $description = 'Total number of '.$key.' documents that matched your query used as reference for offset pagination. When the `total` number of '.$key.' documents available is greater than 5000, total returned will be capped at 5000, and cursor pagination should be used. Read more about [pagination](https://appwrite.io/docs/pagination).'; } else { - $description = 'Total number of ' . $key . ' documents that matched your query.'; + $description = 'Total number of '.$key.' documents that matched your query.'; } $this->addRule('total', [ @@ -52,7 +52,7 @@ class BaseList extends Model } $this->addRule($key, [ 'type' => $model, - 'description' => 'List of ' . $key . '.', + 'description' => 'List of '.$key.'.', 'default' => [], 'array' => true, ]); diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index 0276c1d1f9..16f1b02f24 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -64,14 +64,14 @@ class Bucket extends Model 'description' => 'Allowed file extensions.', 'default' => [], 'example' => ['jpg', 'png'], - 'array' => true + 'array' => true, ]) ->addRule('compression', [ 'type' => self::TYPE_STRING, - 'description' => 'Compression algorithm choosen for compression. Will be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd).', + 'description' => 'Compression algorithm choosen for compression. Will be one of '.COMPRESSION_TYPE_NONE.', ['.COMPRESSION_TYPE_GZIP.'](https://en.wikipedia.org/wiki/Gzip), or ['.COMPRESSION_TYPE_ZSTD.'](https://en.wikipedia.org/wiki/Zstd).', 'default' => '', 'example' => 'gzip', - 'array' => false + 'array' => false, ]) ->addRule('encryption', [ 'type' => self::TYPE_BOOLEAN, @@ -84,8 +84,7 @@ class Bucket extends Model 'description' => 'Virus scanning is enabled.', 'default' => true, 'example' => false, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Build.php b/src/Appwrite/Utopia/Response/Model/Build.php index b76f0ee083..f8709bd027 100644 --- a/src/Appwrite/Utopia/Response/Model/Build.php +++ b/src/Appwrite/Utopia/Response/Model/Build.php @@ -62,8 +62,7 @@ class Build extends Model 'description' => 'The build duration in seconds.', 'default' => 0, 'example' => 0, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Collection.php b/src/Appwrite/Utopia/Response/Model/Collection.php index ae3e283378..2c876f2809 100644 --- a/src/Appwrite/Utopia/Response/Model/Collection.php +++ b/src/Appwrite/Utopia/Response/Model/Collection.php @@ -33,7 +33,7 @@ class Collection extends Model 'description' => 'Collection permissions. [Learn more about permissions](/docs/permissions).', 'default' => '', 'example' => ['read("any")'], - 'array' => true + 'array' => true, ]) ->addRule('databaseId', [ 'type' => self::TYPE_STRING, @@ -82,9 +82,8 @@ class Collection extends Model 'description' => 'Collection indexes.', 'default' => [], 'example' => new \stdClass(), - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Continent.php b/src/Appwrite/Utopia/Response/Model/Continent.php index 5291424a4a..4fd5c9e095 100644 --- a/src/Appwrite/Utopia/Response/Model/Continent.php +++ b/src/Appwrite/Utopia/Response/Model/Continent.php @@ -21,8 +21,7 @@ class Continent extends Model 'description' => 'Continent two letter code.', 'default' => '', 'example' => 'EU', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Country.php b/src/Appwrite/Utopia/Response/Model/Country.php index 64590a54d4..866460f929 100644 --- a/src/Appwrite/Utopia/Response/Model/Country.php +++ b/src/Appwrite/Utopia/Response/Model/Country.php @@ -21,8 +21,7 @@ class Country extends Model 'description' => 'Country two-character ISO 3166-1 alpha code.', 'default' => '', 'example' => 'US', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Currency.php b/src/Appwrite/Utopia/Response/Model/Currency.php index 883ef486d8..e938f8a454 100644 --- a/src/Appwrite/Utopia/Response/Model/Currency.php +++ b/src/Appwrite/Utopia/Response/Model/Currency.php @@ -51,8 +51,7 @@ class Currency extends Model 'description' => 'Currency plural name', 'default' => '', 'example' => 'US dollars', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Database.php b/src/Appwrite/Utopia/Response/Model/Database.php index bd9ae4625c..14e89419c3 100644 --- a/src/Appwrite/Utopia/Response/Model/Database.php +++ b/src/Appwrite/Utopia/Response/Model/Database.php @@ -39,8 +39,7 @@ class Database extends Model 'description' => 'Database enabled.', 'default' => true, 'example' => false, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index 8862d6a14e..be571810b8 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -87,8 +87,7 @@ class Deployment extends Model 'description' => 'The current build time in seconds.', 'default' => 0, 'example' => 128, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Domain.php b/src/Appwrite/Utopia/Response/Model/Domain.php index 135bb52f90..9218a6fdf9 100644 --- a/src/Appwrite/Utopia/Response/Model/Domain.php +++ b/src/Appwrite/Utopia/Response/Model/Domain.php @@ -62,8 +62,7 @@ class Domain extends Model 'description' => 'Certificate ID.', 'default' => '', 'example' => '6ejea5c13377e', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Error.php b/src/Appwrite/Utopia/Response/Model/Error.php index 99cf3cbce2..6fc182214d 100644 --- a/src/Appwrite/Utopia/Response/Model/Error.php +++ b/src/Appwrite/Utopia/Response/Model/Error.php @@ -33,8 +33,7 @@ class Error extends Model 'description' => 'Server version number.', 'default' => '', 'example' => '1.0', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/ErrorDev.php b/src/Appwrite/Utopia/Response/Model/ErrorDev.php index 9319397c77..4911da6bc7 100644 --- a/src/Appwrite/Utopia/Response/Model/ErrorDev.php +++ b/src/Appwrite/Utopia/Response/Model/ErrorDev.php @@ -34,8 +34,7 @@ class ErrorDev extends Error 'default' => [], 'example' => '', 'array' => true, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index 8672a91598..d4bd212e93 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -83,8 +83,7 @@ class Execution extends Model 'description' => 'The script execution duration in seconds.', 'default' => 0, 'example' => 0.400, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/File.php b/src/Appwrite/Utopia/Response/Model/File.php index 53469f46b3..a9a89d2a41 100644 --- a/src/Appwrite/Utopia/Response/Model/File.php +++ b/src/Appwrite/Utopia/Response/Model/File.php @@ -76,8 +76,7 @@ class File extends Model 'description' => 'Total number of chunks uploaded', 'default' => 0, 'example' => 17890, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index c4044c0f2e..b3424b5e7c 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -4,8 +4,6 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -use stdClass; -use Utopia\Database\Document; class Func extends Model { @@ -66,7 +64,7 @@ class Func extends Model 'description' => 'Function variables.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('events', [ 'type' => self::TYPE_STRING, @@ -86,8 +84,7 @@ class Func extends Model 'description' => 'Function execution timeout in seconds.', 'default' => 15, 'example' => 15, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php b/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php index 7a74195371..97d608ff09 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php +++ b/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php @@ -21,8 +21,7 @@ class HealthAntivirus extends Model 'description' => 'Antivirus status. Possible values can are: `disabled`, `offline`, `online`', 'default' => '', 'example' => 'online', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthQueue.php b/src/Appwrite/Utopia/Response/Model/HealthQueue.php index da7c49a43f..5990a4c5d3 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthQueue.php +++ b/src/Appwrite/Utopia/Response/Model/HealthQueue.php @@ -15,8 +15,7 @@ class HealthQueue extends Model 'description' => 'Amount of actions in the queue.', 'default' => 0, 'example' => 8, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthStatus.php b/src/Appwrite/Utopia/Response/Model/HealthStatus.php index ba340107ac..2bd8706763 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthStatus.php +++ b/src/Appwrite/Utopia/Response/Model/HealthStatus.php @@ -27,8 +27,7 @@ class HealthStatus extends Model 'description' => 'Service status. Possible values can are: `pass`, `fail`', 'default' => '', 'example' => 'pass', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthTime.php b/src/Appwrite/Utopia/Response/Model/HealthTime.php index 042d073ce5..0484b8ec33 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthTime.php +++ b/src/Appwrite/Utopia/Response/Model/HealthTime.php @@ -27,8 +27,7 @@ class HealthTime extends Model 'description' => 'Difference of unix remote and local timestamps in milliseconds.', 'default' => 0, 'example' => 93, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthVersion.php b/src/Appwrite/Utopia/Response/Model/HealthVersion.php index 15a73c0e75..6fab34576d 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthVersion.php +++ b/src/Appwrite/Utopia/Response/Model/HealthVersion.php @@ -15,8 +15,7 @@ class HealthVersion extends Model 'description' => 'Version of the Appwrite instance.', 'default' => '', 'example' => '0.11.0', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Identity.php b/src/Appwrite/Utopia/Response/Model/Identity.php index ff7f57a3e6..c23948acbf 100644 --- a/src/Appwrite/Utopia/Response/Model/Identity.php +++ b/src/Appwrite/Utopia/Response/Model/Identity.php @@ -69,8 +69,7 @@ class Identity extends Model 'description' => 'Identity Provider Refresh Token.', 'default' => '', 'example' => 'MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php index 3d3d1a3b52..dcda9d11c6 100644 --- a/src/Appwrite/Utopia/Response/Model/Index.php +++ b/src/Appwrite/Utopia/Response/Model/Index.php @@ -48,8 +48,7 @@ class Index extends Model 'example' => [], 'array' => true, 'required' => false, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/JWT.php b/src/Appwrite/Utopia/Response/Model/JWT.php index a2563a2ad8..debb81b28e 100644 --- a/src/Appwrite/Utopia/Response/Model/JWT.php +++ b/src/Appwrite/Utopia/Response/Model/JWT.php @@ -14,8 +14,7 @@ class JWT extends Model 'type' => self::TYPE_STRING, 'description' => 'JWT encoded string.', 'example' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 1179a73d62..1dba4e771b 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -60,18 +60,17 @@ class Key extends Model ]) ->addRule('accessedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after ' . APP_KEY_ACCCESS / 60 / 60 . ' hours.', + 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after '.APP_KEY_ACCCESS / 60 / 60 .' hours.', 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE + 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('sdks', [ 'type' => self::TYPE_STRING, 'description' => 'List of SDK user agents that used this key.', 'default' => null, 'example' => 'appwrite:flutter', - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Language.php b/src/Appwrite/Utopia/Response/Model/Language.php index 64f99a006f..c3f1072c82 100644 --- a/src/Appwrite/Utopia/Response/Model/Language.php +++ b/src/Appwrite/Utopia/Response/Model/Language.php @@ -27,8 +27,7 @@ class Language extends Model 'description' => 'Language native name.', 'default' => '', 'example' => 'Italiano', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Locale.php b/src/Appwrite/Utopia/Response/Model/Locale.php index fdfa363acd..61f371e7ac 100644 --- a/src/Appwrite/Utopia/Response/Model/Locale.php +++ b/src/Appwrite/Utopia/Response/Model/Locale.php @@ -51,8 +51,7 @@ class Locale extends Model 'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format', 'default' => '', 'example' => 'USD', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/LocaleCode.php b/src/Appwrite/Utopia/Response/Model/LocaleCode.php index e73ceff6a5..d629c9a1a5 100644 --- a/src/Appwrite/Utopia/Response/Model/LocaleCode.php +++ b/src/Appwrite/Utopia/Response/Model/LocaleCode.php @@ -21,8 +21,7 @@ class LocaleCode extends Model 'description' => 'Locale name', 'default' => '', 'example' => 'US', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Log.php b/src/Appwrite/Utopia/Response/Model/Log.php index bc2c923494..7177cad078 100644 --- a/src/Appwrite/Utopia/Response/Model/Log.php +++ b/src/Appwrite/Utopia/Response/Model/Log.php @@ -135,8 +135,7 @@ class Log extends Model 'description' => 'Country name.', 'default' => '', 'example' => 'United States', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Membership.php b/src/Appwrite/Utopia/Response/Model/Membership.php index c134142185..2364ca5ec8 100644 --- a/src/Appwrite/Utopia/Response/Model/Membership.php +++ b/src/Appwrite/Utopia/Response/Model/Membership.php @@ -82,8 +82,7 @@ class Membership extends Model 'default' => [], 'example' => ['owner'], 'array' => true, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Metric.php b/src/Appwrite/Utopia/Response/Model/Metric.php index 16cf7f7df2..6b52f97e21 100644 --- a/src/Appwrite/Utopia/Response/Model/Metric.php +++ b/src/Appwrite/Utopia/Response/Model/Metric.php @@ -20,7 +20,7 @@ class Metric extends Model 'type' => self::TYPE_DATETIME, 'description' => 'The date at which this metric was aggregated in ISO 8601 format.', 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE + 'example' => self::TYPE_DATETIME_EXAMPLE, ]); } diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 78e8658032..33bccd23d2 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -51,7 +51,7 @@ class Migration extends Model 'description' => 'Resources to migration.', 'default' => [], 'example' => ['user'], - 'array' => true + 'array' => true, ]) ->addRule('statusCounters', [ 'type' => self::TYPE_JSON, @@ -70,8 +70,7 @@ class Migration extends Model 'description' => 'All errors that occurred during the migration process.', 'default' => [], 'example' => [], - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Mock.php b/src/Appwrite/Utopia/Response/Model/Mock.php index afdae66084..7332e589f1 100644 --- a/src/Appwrite/Utopia/Response/Model/Mock.php +++ b/src/Appwrite/Utopia/Response/Model/Mock.php @@ -15,8 +15,7 @@ class Mock extends Model 'description' => 'Result message.', 'default' => '', 'example' => 'Success', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Phone.php b/src/Appwrite/Utopia/Response/Model/Phone.php index 226955919b..d732d0dc2e 100644 --- a/src/Appwrite/Utopia/Response/Model/Phone.php +++ b/src/Appwrite/Utopia/Response/Model/Phone.php @@ -27,8 +27,7 @@ class Phone extends Model 'description' => 'Country name.', 'default' => '', 'example' => 'United States', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Platform.php b/src/Appwrite/Utopia/Response/Model/Platform.php index 4b8ffb1486..a25d819947 100644 --- a/src/Appwrite/Utopia/Response/Model/Platform.php +++ b/src/Appwrite/Utopia/Response/Model/Platform.php @@ -73,8 +73,7 @@ class Platform extends Model 'description' => 'HTTP basic authentication password.', 'default' => '', 'example' => 'password', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Project.php b/src/Appwrite/Utopia/Response/Model/Project.php index 35c3cf0e1f..511952b142 100644 --- a/src/Appwrite/Utopia/Response/Model/Project.php +++ b/src/Appwrite/Utopia/Response/Model/Project.php @@ -178,7 +178,7 @@ class Project extends Model 'description' => 'Status for custom SMTP', 'default' => false, 'example' => false, - 'array' => false + 'array' => false, ]) ->addRule('smtpSender', [ 'type' => self::TYPE_STRING, @@ -215,8 +215,7 @@ class Project extends Model 'description' => 'SMTP server secure protocol', 'default' => '', 'example' => 'tls', - ]) - ; + ]); $services = Config::getParam('services', []); $auth = Config::getParam('auth', []); @@ -226,17 +225,16 @@ class Project extends Model $key = $method['key'] ?? ''; $this - ->addRule('auth' . ucfirst($key), [ + ->addRule('auth'.ucfirst($key), [ 'type' => self::TYPE_BOOLEAN, - 'description' => $name . ' auth method status', + 'description' => $name.' auth method status', 'example' => true, 'default' => true, - ]) - ; + ]); } foreach ($services as $service) { - if (!$service['optional']) { + if (! $service['optional']) { continue; } @@ -244,13 +242,12 @@ class Project extends Model $key = $service['key'] ?? ''; $this - ->addRule('serviceStatusFor' . ucfirst($key), [ + ->addRule('serviceStatusFor'.ucfirst($key), [ 'type' => self::TYPE_BOOLEAN, - 'description' => $name . ' service status', + 'description' => $name.' service status', 'example' => true, 'default' => true, - ]) - ; + ]); } } @@ -296,12 +293,12 @@ class Project extends Model $services = Config::getParam('services', []); foreach ($services as $service) { - if (!$service['optional']) { + if (! $service['optional']) { continue; } $key = $service['key'] ?? ''; $value = $values[$key] ?? true; - $document->setAttribute('serviceStatusFor' . ucfirst($key), $value); + $document->setAttribute('serviceStatusFor'.ucfirst($key), $value); } // Auth @@ -318,7 +315,7 @@ class Project extends Model foreach ($auth as $index => $method) { $key = $method['key']; $value = $authValues[$key] ?? true; - $document->setAttribute('auth' . ucfirst($key), $value); + $document->setAttribute('auth'.ucfirst($key), $value); } // Providers @@ -327,7 +324,7 @@ class Project extends Model $projectProviders = []; foreach ($providers as $key => $provider) { - if (!$provider['enabled']) { + if (! $provider['enabled']) { // Disabled by Appwrite configuration, exclude from response continue; } @@ -335,13 +332,13 @@ class Project extends Model $projectProviders[] = new Document([ 'key' => $key, 'name' => $provider['name'] ?? '', - 'appId' => $providerValues[$key . 'Appid'] ?? '', - 'secret' => $providerValues[$key . 'Secret'] ?? '', - 'enabled' => $providerValues[$key . 'Enabled'] ?? false, + 'appId' => $providerValues[$key.'Appid'] ?? '', + 'secret' => $providerValues[$key.'Secret'] ?? '', + 'enabled' => $providerValues[$key.'Enabled'] ?? false, ]); } - $document->setAttribute("providers", $projectProviders); + $document->setAttribute('providers', $projectProviders); return $document; } diff --git a/src/Appwrite/Utopia/Response/Model/Runtime.php b/src/Appwrite/Utopia/Response/Model/Runtime.php index 8bc42cb418..43cf711994 100644 --- a/src/Appwrite/Utopia/Response/Model/Runtime.php +++ b/src/Appwrite/Utopia/Response/Model/Runtime.php @@ -20,7 +20,7 @@ class Runtime extends Model 'type' => self::TYPE_STRING, 'description' => 'Runtime Name.', 'default' => '', - 'example' => 'Python' + 'example' => 'Python', ]) ->addRule('version', [ 'type' => self::TYPE_STRING, @@ -52,8 +52,7 @@ class Runtime extends Model 'default' => '', 'example' => 'amd64', 'array' => true, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Session.php b/src/Appwrite/Utopia/Response/Model/Session.php index d961966b24..7b71780c4e 100644 --- a/src/Appwrite/Utopia/Response/Model/Session.php +++ b/src/Appwrite/Utopia/Response/Model/Session.php @@ -159,8 +159,7 @@ class Session extends Model 'description' => 'Returns true if this the current user session.', 'default' => false, 'example' => true, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Team.php b/src/Appwrite/Utopia/Response/Model/Team.php index d080a82bb1..e180afbbeb 100644 --- a/src/Appwrite/Utopia/Response/Model/Team.php +++ b/src/Appwrite/Utopia/Response/Model/Team.php @@ -46,8 +46,7 @@ class Team extends Model 'description' => 'Team preferences as a key-value object', 'default' => new \stdClass(), 'example' => ['theme' => 'pink', 'timezone' => 'UTC'], - ]) - ; + ]); } /** @@ -65,6 +64,7 @@ class Team extends Model if (is_array($prefs) && empty($prefs)) { $document->setAttribute('prefs', new \stdClass()); } + return $document; } diff --git a/src/Appwrite/Utopia/Response/Model/Template.php b/src/Appwrite/Utopia/Response/Model/Template.php index 3ce9cacdb3..9d4f81068a 100644 --- a/src/Appwrite/Utopia/Response/Model/Template.php +++ b/src/Appwrite/Utopia/Response/Model/Template.php @@ -26,7 +26,6 @@ abstract class Template extends Model 'description' => 'Template message', 'default' => '', 'example' => 'Click on the link to verify your account.', - ]) - ; + ]); } } diff --git a/src/Appwrite/Utopia/Response/Model/TemplateEmail.php b/src/Appwrite/Utopia/Response/Model/TemplateEmail.php index ecdf89e774..1babef9f90 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateEmail.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateEmail.php @@ -33,8 +33,7 @@ class TemplateEmail extends Template 'description' => 'Email subject', 'default' => '', 'example' => 'Please verify your email address', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/TemplateSMS.php b/src/Appwrite/Utopia/Response/Model/TemplateSMS.php index 2b19ef4878..f0abcdc511 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateSMS.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateSMS.php @@ -10,6 +10,7 @@ class TemplateSMS extends Template { parent::__construct(); } + /** * Get Name * diff --git a/src/Appwrite/Utopia/Response/Model/Token.php b/src/Appwrite/Utopia/Response/Model/Token.php index c409e37f03..05bbe10302 100644 --- a/src/Appwrite/Utopia/Response/Model/Token.php +++ b/src/Appwrite/Utopia/Response/Model/Token.php @@ -39,8 +39,7 @@ class Token extends Model 'description' => 'Token expiration date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php index 83b8744760..1f708a0b4d 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php +++ b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php @@ -21,16 +21,15 @@ class UsageBuckets extends Model 'description' => 'Aggregated stats for total number of files in this bucket.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total storage of files in this bucket.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageCollection.php b/src/Appwrite/Utopia/Response/Model/UsageCollection.php index 5abcf46b7d..fd5350af86 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageCollection.php +++ b/src/Appwrite/Utopia/Response/Model/UsageCollection.php @@ -21,9 +21,8 @@ class UsageCollection extends Model 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index 58d49c506e..fac50676a6 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -21,16 +21,15 @@ class UsageDatabase extends Model 'description' => 'Aggregated stats for total number of collections.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index a6008ca9e6..20c2a1aecb 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -21,23 +21,22 @@ class UsageDatabases extends Model 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('collectionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of collections.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunction.php b/src/Appwrite/Utopia/Response/Model/UsageFunction.php index 03acaa750a..013bf4056d 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunction.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunction.php @@ -21,42 +21,42 @@ class UsageFunction extends Model 'description' => 'Aggregated stats for number of function deployments.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('deploymentsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function deployments storage.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('buildsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function builds.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('buildsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for builds storage.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('buildsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function build compute.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function executions.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('executionsTime', [ @@ -64,9 +64,8 @@ class UsageFunction extends Model 'description' => 'Aggregated stats for function execution compute.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php index 6ab36e21ac..003f6390ad 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php @@ -21,49 +21,49 @@ class UsageFunctions extends Model 'description' => 'Aggregated stats for number of functions.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('deploymentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function deployments.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('deploymentsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function deployments storage.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('buildsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function builds.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('buildsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for builds storage.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('buildsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function build compute.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function executions.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('executionsTime', [ @@ -71,9 +71,8 @@ class UsageFunctions extends Model 'description' => 'Aggregated stats for function execution compute.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 641613809a..41acef102f 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -21,58 +21,57 @@ class UsageProject extends Model 'description' => 'Aggregated stats for number of requests.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('network', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for consumed bandwidth.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function executions.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of documents.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('databasesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of databases.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('usersTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of users.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('bucketsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of buckets.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageStorage.php b/src/Appwrite/Utopia/Response/Model/UsageStorage.php index 88d0beca01..4d83948fb8 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageStorage.php +++ b/src/Appwrite/Utopia/Response/Model/UsageStorage.php @@ -21,23 +21,22 @@ class UsageStorage extends Model 'description' => 'Aggregated stats for total number of buckets.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('filesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of files.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageUsers.php b/src/Appwrite/Utopia/Response/Model/UsageUsers.php index c0cc4baa54..71774bf61d 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageUsers.php +++ b/src/Appwrite/Utopia/Response/Model/UsageUsers.php @@ -21,7 +21,7 @@ class UsageUsers extends Model 'description' => 'Aggregated stats for total number of users.', 'default' => [], 'example' => [], - 'array' => true + 'array' => true, ]) ->addRule('sessionsTotal', [ @@ -29,9 +29,8 @@ class UsageUsers extends Model 'description' => 'Aggregated stats for sessions created.', 'default' => [], 'example' => [], - 'array' => true - ]) - ; + 'array' => true, + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/User.php b/src/Appwrite/Utopia/Response/Model/User.php index d6988b47f4..a69c30f9d1 100644 --- a/src/Appwrite/Utopia/Response/Model/User.php +++ b/src/Appwrite/Utopia/Response/Model/User.php @@ -129,11 +129,10 @@ class User extends Model ]) ->addRule('accessedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after ' . APP_USER_ACCCESS / 60 / 60 . ' hours.', + 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after '.APP_USER_ACCCESS / 60 / 60 .' hours.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ; + ]); } /** @@ -151,6 +150,7 @@ class User extends Model if (is_array($prefs) && empty($prefs)) { $document->setAttribute('prefs', new \stdClass()); } + return $document; } diff --git a/src/Appwrite/Utopia/Response/Model/Variable.php b/src/Appwrite/Utopia/Response/Model/Variable.php index f4b3bcf2bb..7d84e8803f 100644 --- a/src/Appwrite/Utopia/Response/Model/Variable.php +++ b/src/Appwrite/Utopia/Response/Model/Variable.php @@ -46,8 +46,7 @@ class Variable extends Model 'description' => 'Function ID.', 'default' => '', 'example' => '5e5ea5c16897e', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Webhook.php b/src/Appwrite/Utopia/Response/Model/Webhook.php index 781bb9186d..d9e0f4be3c 100644 --- a/src/Appwrite/Utopia/Response/Model/Webhook.php +++ b/src/Appwrite/Utopia/Response/Model/Webhook.php @@ -75,8 +75,7 @@ class Webhook extends Model 'description' => 'Signature key which can be used to validated incoming', 'default' => '', 'example' => 'ad3d581ca230e2b7059c545e5a', - ]) - ; + ]); } /** diff --git a/src/Appwrite/Utopia/View.php b/src/Appwrite/Utopia/View.php index e4ed8164c9..ba0a1f0fc6 100644 --- a/src/Appwrite/Utopia/View.php +++ b/src/Appwrite/Utopia/View.php @@ -11,8 +11,9 @@ class View extends OldView * * Convert all applicable characters to HTML entities * - * @param string $str + * @param string $str * @return string + * * @deprecated Use print method with escape filter */ public function escape($str) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index bd49e5cf20..4e158eb362 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -8,13 +8,21 @@ use Utopia\App; class Executor { public const METHOD_GET = 'GET'; + public const METHOD_POST = 'POST'; + public const METHOD_PUT = 'PUT'; + public const METHOD_PATCH = 'PATCH'; + public const METHOD_DELETE = 'DELETE'; + public const METHOD_HEAD = 'HEAD'; + public const METHOD_OPTIONS = 'OPTIONS'; + public const METHOD_CONNECT = 'CONNECT'; + public const METHOD_TRACE = 'TRACE'; private bool $selfSigned = false; @@ -29,7 +37,7 @@ class Executor public function __construct(string $endpoint) { - if (!filter_var($endpoint, FILTER_VALIDATE_URL)) { + if (! filter_var($endpoint, FILTER_VALIDATE_URL)) { throw new Exception('Unsupported endpoint'); } @@ -38,7 +46,7 @@ class Executor $this->memory = intval(App::getEnv('_APP_FUNCTIONS_MEMORY', '512')); $this->headers = [ 'content-type' => 'application/json', - 'authorization' => 'Bearer ' . App::getEnv('_APP_EXECUTOR_SECRET', ''), + 'authorization' => 'Bearer '.App::getEnv('_APP_EXECUTOR_SECRET', ''), ]; } @@ -47,16 +55,16 @@ class Executor * * Launches a runtime container for a deployment ready for execution * - * @param string $deploymentId - * @param string $projectId - * @param string $source - * @param string $image - * @param bool $remove - * @param string $entrypoint - * @param string $workdir - * @param string $destination - * @param array $variables - * @param array $commands + * @param string $deploymentId + * @param string $projectId + * @param string $source + * @param string $image + * @param bool $remove + * @param string $entrypoint + * @param string $workdir + * @param string $destination + * @param array $variables + * @param array $commands */ public function createRuntime( string $deploymentId, @@ -71,8 +79,8 @@ class Executor array $commands = [] ) { $runtimeId = "$projectId-$deploymentId"; - $route = "/runtimes"; - $headers = [ 'x-opr-runtime-id' => $runtimeId ]; + $route = '/runtimes'; + $headers = ['x-opr-runtime-id' => $runtimeId]; $params = [ 'runtimeId' => $runtimeId, 'source' => $source, @@ -87,7 +95,7 @@ class Executor 'memory' => $this->memory, ]; - $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); + $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $timeout); @@ -103,15 +111,14 @@ class Executor /** * Create an execution * - * @param string $projectId - * @param string $deploymentId - * @param string $payload - * @param array $variables - * @param int $timeout - * @param string $image - * @param string $source - * @param string $entrypoint - * + * @param string $projectId + * @param string $deploymentId + * @param string $payload + * @param array $variables + * @param int $timeout + * @param string $image + * @param string $source + * @param string $entrypoint * @return array */ public function createExecution( @@ -125,8 +132,8 @@ class Executor string $entrypoint, ) { $runtimeId = "$projectId-$deploymentId"; - $route = '/runtimes/' . $runtimeId . '/execution'; - $headers = [ 'x-opr-runtime-id' => $runtimeId ]; + $route = '/runtimes/'.$runtimeId.'/execution'; + $headers = ['x-opr-runtime-id' => $runtimeId]; $params = [ 'runtimeId' => $runtimeId, 'variables' => $variables, @@ -140,7 +147,7 @@ class Executor 'memory' => $this->memory, ]; - $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); + $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $timeout); @@ -158,22 +165,23 @@ class Executor * * Make an API call * - * @param string $method - * @param string $path - * @param array $params - * @param array $headers - * @param bool $decode + * @param string $method + * @param string $path + * @param array $params + * @param array $headers + * @param bool $decode * @return array|string + * * @throws Exception */ public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15) { - $headers = array_merge($this->headers, $headers); - $ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); - $responseHeaders = []; - $responseStatus = -1; - $responseType = ''; - $responseBody = ''; + $headers = array_merge($this->headers, $headers); + $ch = curl_init($this->endpoint.$path.(($method == self::METHOD_GET && ! empty($params)) ? '?'.http_build_query($params) : '')); + $responseHeaders = []; + $responseStatus = -1; + $responseType = ''; + $responseBody = ''; switch ($headers['content-type']) { case 'application/json': @@ -190,7 +198,7 @@ class Executor } foreach ($headers as $i => $header) { - $headers[] = $i . ':' . $header; + $headers[] = $i.':'.$header; unset($headers[$i]); } @@ -223,8 +231,8 @@ class Executor curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - $responseBody = curl_exec($ch); - $responseType = $responseHeaders['content-type'] ?? ''; + $responseBody = curl_exec($ch); + $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($decode) { @@ -233,7 +241,7 @@ class Executor $json = json_decode($responseBody, true); if ($json === null) { - throw new Exception('Failed to parse response: ' . $responseBody); + throw new Exception('Failed to parse response: '.$responseBody); } $responseBody = $json; @@ -243,7 +251,7 @@ class Executor } if ((curl_errno($ch)/* || 200 != $responseStatus*/)) { - throw new Exception(curl_error($ch) . ' with status code ' . $responseStatus, $responseStatus); + throw new Exception(curl_error($ch).' with status code '.$responseStatus, $responseStatus); } curl_close($ch); @@ -252,21 +260,21 @@ class Executor return [ 'headers' => $responseHeaders, - 'body' => $responseBody + 'body' => $responseBody, ]; } /** * Parse Cookie String * - * @param string $cookie + * @param string $cookie * @return array */ public function parseCookie(string $cookie): array { $cookies = []; - parse_str(strtr($cookie, array('&' => '%26', '+' => '%2B', ';' => '&')), $cookies); + parse_str(strtr($cookie, ['&' => '%26', '+' => '%2B', ';' => '&']), $cookies); return $cookies; } @@ -274,8 +282,8 @@ class Executor /** * Flatten params array to PHP multiple format * - * @param array $data - * @param string $prefix + * @param array $data + * @param string $prefix * @return array */ protected function flatten(array $data, string $prefix = ''): array diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index 21e4ccc958..6a9176232b 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -7,13 +7,21 @@ use Exception; class Client { public const METHOD_GET = 'GET'; + public const METHOD_POST = 'POST'; + public const METHOD_PUT = 'PUT'; + public const METHOD_PATCH = 'PATCH'; + public const METHOD_DELETE = 'DELETE'; + public const METHOD_HEAD = 'HEAD'; + public const METHOD_OPTIONS = 'OPTIONS'; + public const METHOD_CONNECT = 'CONNECT'; + public const METHOD_TRACE = 'TRACE'; /** @@ -52,8 +60,7 @@ class Client * * Your Appwrite project ID. You can find your project ID in your Appwrite console project settings. * - * @param string $value - * + * @param string $value * @return self $this */ public function setProject(string $value): self @@ -68,8 +75,7 @@ class Client * * Your Appwrite project secret key. You can can create a new API key from your Appwrite console API keys dashboard. * - * @param string $value - * + * @param string $value * @return self $this */ public function setKey(string $value): self @@ -82,8 +88,7 @@ class Client /** * Set Locale * - * @param string $value - * + * @param string $value * @return self $this */ public function setLocale(string $value): self @@ -96,8 +101,7 @@ class Client /** * Set Mode * - * @param string $value - * + * @param string $value * @return self $this */ public function setMode(string $value): self @@ -108,7 +112,7 @@ class Client } /** - * @param bool $status true + * @param bool $status true * @return self $this */ public function setSelfSigned(bool $status = true): self @@ -119,7 +123,7 @@ class Client } /** - * @param string $endpoint + * @param string $endpoint * @return self $this */ public function setEndpoint(string $endpoint): self @@ -138,9 +142,8 @@ class Client } /** - * @param string $key - * @param string $value - * + * @param string $key + * @param string $value * @return self $this */ public function addHeader(string $key, string $value): self @@ -155,19 +158,20 @@ class Client * * Make an API call * - * @param string $method - * @param string $path - * @param array $params - * @param array $headers - * @param bool $decode + * @param string $method + * @param string $path + * @param array $params + * @param array $headers + * @param bool $decode * @return array + * * @throws Exception */ public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true): array { - $headers = array_merge($this->headers, $headers); - $ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); - $responseHeaders = []; + $headers = array_merge($this->headers, $headers); + $ch = curl_init($this->endpoint.$path.(($method == self::METHOD_GET && ! empty($params)) ? '?'.http_build_query($params) : '')); + $responseHeaders = []; $query = match ($headers['content-type']) { 'application/json' => json_encode($params), @@ -177,7 +181,7 @@ class Client }; foreach ($headers as $i => $header) { - $headers[] = $i . ':' . $header; + $headers[] = $i.':'.$header; unset($headers[$i]); } @@ -212,15 +216,15 @@ class Client curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - $responseBody = curl_exec($ch); - $responseType = $responseHeaders['content-type'] ?? ''; + $responseBody = curl_exec($ch); + $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($decode && substr($responseType, 0, strpos($responseType, ';')) == 'application/json') { $json = json_decode($responseBody, true); if ($json === null) { - throw new Exception('Failed to parse response: ' . $responseBody); + throw new Exception('Failed to parse response: '.$responseBody); } $responseBody = $json; @@ -228,7 +232,7 @@ class Client } if ((curl_errno($ch))) { - throw new Exception(curl_error($ch) . ' with status code ' . $responseStatus, $responseStatus); + throw new Exception(curl_error($ch).' with status code '.$responseStatus, $responseStatus); } curl_close($ch); @@ -236,19 +240,19 @@ class Client $responseHeaders['status-code'] = $responseStatus; if ($responseStatus === 500) { - echo 'Server error(' . $method . ': ' . $path . '. Params: ' . json_encode($params) . '): ' . json_encode($responseBody) . "\n"; + echo 'Server error('.$method.': '.$path.'. Params: '.json_encode($params).'): '.json_encode($responseBody)."\n"; } return [ 'headers' => $responseHeaders, - 'body' => $responseBody + 'body' => $responseBody, ]; } /** * Parse Cookie String * - * @param string $cookie + * @param string $cookie * @return array */ public function parseCookie(string $cookie): array @@ -263,8 +267,8 @@ class Client /** * Flatten params array to PHP multiple format * - * @param array $data - * @param string $prefix + * @param array $data + * @param string $prefix * @return array */ protected function flatten(array $data, string $prefix = ''): array diff --git a/tests/e2e/General/AbuseTest.php b/tests/e2e/General/AbuseTest.php index f5a2829974..ded164af21 100644 --- a/tests/e2e/General/AbuseTest.php +++ b/tests/e2e/General/AbuseTest.php @@ -34,13 +34,13 @@ class AbuseTest extends Scope $max = 120; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'documentId' => ID::unique(), 'data' => [ - 'title' => 'The Hulk ' . $i, + 'title' => 'The Hulk '.$i, ], ]); @@ -59,7 +59,7 @@ class AbuseTest extends Scope $collectionId = $data['collectionId']; $max = 120; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -73,12 +73,12 @@ class AbuseTest extends Scope $documentId = $document['body']['$id']; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$documentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'data' => [ - 'title' => 'The Hulk ' . $i, + 'title' => 'The Hulk '.$i, ], ]); @@ -98,7 +98,7 @@ class AbuseTest extends Scope $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -111,7 +111,7 @@ class AbuseTest extends Scope $documentId = $document['body']['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$documentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -131,12 +131,12 @@ class AbuseTest extends Scope $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../resources/logo.png'), 'image/png', 'permissions.png'), ]); if ($i < $max) { @@ -153,23 +153,23 @@ class AbuseTest extends Scope $bucketId = $data['bucketId']; $max = 60; - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $response['body']['$id']; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $response = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'name' => 'permissions' . $i . '.png', + 'name' => 'permissions'.$i.'.png', ]); if ($i < $max) { @@ -187,18 +187,18 @@ class AbuseTest extends Scope $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -216,7 +216,7 @@ class AbuseTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'AbuseDatabase', @@ -227,10 +227,10 @@ class AbuseTest extends Scope $databaseId = $database['body']['$id']; - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', [ + $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -244,10 +244,10 @@ class AbuseTest extends Scope $collectionId = $movies['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', [ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'key' => 'title', 'size' => 256, diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 087b984f9d..e3533e31d6 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -68,7 +68,7 @@ class HTTPTest extends Scope { // Preparation $previousEndpoint = $this->client->getEndpoint(); - $this->client->setEndpoint("http://localhost"); + $this->client->setEndpoint('http://localhost'); /** * Test for SUCCESS @@ -96,7 +96,7 @@ class HTTPTest extends Scope public function testSpecs() { - $directory = __DIR__ . '/../../../app/config/specs/'; + $directory = __DIR__.'/../../../app/config/specs/'; $files = scandir($directory); $client = new Client(); @@ -120,7 +120,7 @@ class HTTPTest extends Scope break; } } - if (!$allowed) { + if (! $allowed) { continue; } @@ -129,7 +129,7 @@ class HTTPTest extends Scope */ $response = $client->call(Client::METHOD_POST, '/validator/debug', [ 'content-type' => 'application/json', - ], json_decode(file_get_contents($directory . $file), true)); + ], json_decode(file_get_contents($directory.$file), true)); $response['body'] = json_decode($response['body'], true); $this->assertEquals(200, $response['headers']['status-code']); diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index c8c4f21165..d9a662b6ac 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -2,13 +2,12 @@ namespace Tests\E2E\General; +use CURLFile; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use CURLFile; use Tests\E2E\Services\Functions\FunctionsBase; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -20,6 +19,7 @@ class UsageTest extends Scope use FunctionsBase; private const WAIT = 35; + private const CREATE = 20; protected string $projectId; @@ -46,21 +46,21 @@ class UsageTest extends Scope $headers['x-appwrite-key'] = $project['apiKey']; $headers['content-type'] = 'application/json'; - $usersTotal = 0; + $usersTotal = 0; $requestsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { - $email = uniqid() . 'user@usage.test'; + $email = uniqid().'user@usage.test'; $password = 'password'; - $name = uniqid() . 'User'; + $name = uniqid().'User'; $res = $this->client->call( Client::METHOD_POST, '/users', $headers, [ - 'userId' => 'unique()', - 'email' => $email, + 'userId' => 'unique()', + 'email' => $email, 'password' => $password, - 'name' => $name, + 'name' => $name, ] ); @@ -71,7 +71,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $userId = $res['body']['$id']; - $res = $this->client->call(Client::METHOD_DELETE, '/users/' . $userId, $headers); + $res = $this->client->call(Client::METHOD_DELETE, '/users/'.$userId, $headers); $this->assertEmpty($res['body']); $requestsTotal++; $usersTotal--; @@ -79,10 +79,10 @@ class UsageTest extends Scope } return [ - 'projectId' => $projectId, - 'headers' => $headers, - 'usersTotal' => $usersTotal, - 'requestsTotal' => $requestsTotal + 'projectId' => $projectId, + 'headers' => $headers, + 'usersTotal' => $usersTotal, + 'requestsTotal' => $requestsTotal, ]; } @@ -93,15 +93,15 @@ class UsageTest extends Scope { sleep(self::WAIT); - $projectId = $data['projectId']; - $headers = $data['headers']; - $usersTotal = $data['usersTotal']; + $projectId = $data['projectId']; + $headers = $data['headers']; + $usersTotal = $data['usersTotal']; $requestsTotal = $data['requestsTotal']; $consoleHeaders = [ 'origin' => 'http://localhost', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], 'x-appwrite-project' => $projectId, 'x-appwrite-mode' => 'admin', ]; @@ -151,9 +151,8 @@ class UsageTest extends Scope $storageTotal = 0; $filesTotal = 0; - for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid() . ' bucket'; + $name = uniqid().' bucket'; $res = $this->client->call( Client::METHOD_POST, '/storage/buckets', @@ -179,7 +178,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/storage/buckets/' . $bucketId, + '/storage/buckets/'.$bucketId, $headers ); $this->assertEmpty($res['body']); @@ -191,19 +190,19 @@ class UsageTest extends Scope // upload some files $files = [ [ - 'path' => realpath(__DIR__ . '/../../resources/logo.png'), + 'path' => realpath(__DIR__.'/../../resources/logo.png'), 'name' => 'logo.png', ], [ - 'path' => realpath(__DIR__ . '/../../resources/file.png'), + 'path' => realpath(__DIR__.'/../../resources/file.png'), 'name' => 'file.png', ], [ - 'path' => realpath(__DIR__ . '/../../resources/disk-a/kitten-3.gif'), + 'path' => realpath(__DIR__.'/../../resources/disk-a/kitten-3.gif'), 'name' => 'kitten-3.gif', ], [ - 'path' => realpath(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'), + 'path' => realpath(__DIR__.'/../../resources/disk-a/kitten-1.jpg'), 'name' => 'kitten-1.jpg', ], ]; @@ -213,7 +212,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_POST, - '/storage/buckets/' . $bucketId . '/files', + '/storage/buckets/'.$bucketId.'/files', array_merge($headers, ['content-type' => 'multipart/form-data']), [ 'fileId' => 'unique()', @@ -232,13 +231,13 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/storage/buckets/' . $bucketId . '/files/' . $fileId, + '/storage/buckets/'.$bucketId.'/files/'.$fileId, $headers ); $this->assertEmpty($res['body']); $requestsTotal++; $filesTotal--; - $storageTotal -= $fileSize; + $storageTotal -= $fileSize; } } @@ -256,11 +255,11 @@ class UsageTest extends Scope */ public function testStorageStats(array $data): array { - $bucketId = $data['bucketId']; - $bucketsTotal = $data['bucketsTotal']; + $bucketId = $data['bucketId']; + $bucketsTotal = $data['bucketsTotal']; $requestsTotal = $data['requestsTotal']; - $storageTotal = $data['storageTotal']; - $filesTotal = $data['filesTotal']; + $storageTotal = $data['storageTotal']; + $filesTotal = $data['filesTotal']; sleep(self::WAIT); @@ -301,7 +300,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_GET, - '/storage/' . $bucketId . '/usage?range=30d', + '/storage/'.$bucketId.'/usage?range=30d', array_merge( $data['headers'], $data['consoleHeaders'] @@ -328,7 +327,7 @@ class UsageTest extends Scope $documentsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid() . ' database'; + $name = uniqid().' database'; $res = $this->client->call( Client::METHOD_POST, '/databases', @@ -339,7 +338,6 @@ class UsageTest extends Scope ] ); - $this->assertEquals($name, $res['body']['name']); $this->assertNotEmpty($res['body']['$id']); $databaseId = $res['body']['$id']; @@ -350,7 +348,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/databases/' . $databaseId, + '/databases/'.$databaseId, $headers ); $this->assertEmpty($res['body']); @@ -361,10 +359,10 @@ class UsageTest extends Scope } for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid() . ' collection'; + $name = uniqid().' collection'; $res = $this->client->call( Client::METHOD_POST, - '/databases/' . $databaseId . '/collections', + '/databases/'.$databaseId.'/collections', $headers, [ 'collectionId' => 'unique()', @@ -389,7 +387,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/databases/' . $databaseId . '/collections/' . $collectionId, + '/databases/'.$databaseId.'/collections/'.$collectionId, $headers ); $this->assertEmpty($res['body']); @@ -400,7 +398,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_POST, - '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes' . '/string', + '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes'.'/string', $headers, [ 'key' => 'name', @@ -415,14 +413,14 @@ class UsageTest extends Scope sleep(self::WAIT); for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid() . ' collection'; + $name = uniqid().' collection'; $res = $this->client->call( Client::METHOD_POST, - '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', + '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', $headers, [ 'documentId' => 'unique()', - 'data' => ['name' => $name] + 'data' => ['name' => $name], ] ); $this->assertEquals($name, $res['body']['name']); @@ -435,7 +433,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, + '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$documentId, $headers ); $this->assertEmpty($res['body']); @@ -455,10 +453,8 @@ class UsageTest extends Scope } /** @depends testPrepareDatabaseStats */ - public function testDatabaseStats(array $data): array { - $projectId = $data['projectId']; $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; @@ -502,7 +498,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_GET, - '/databases/' . $databaseId . '/usage?range=30d', + '/databases/'.$databaseId.'/usage?range=30d', $data['consoleHeaders'] ); $res = $res['body']; @@ -513,7 +509,7 @@ class UsageTest extends Scope $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); $this->validateDates($res['documentsTotal']); - $res = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', $data['consoleHeaders']); + $res = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/usage?range=30d', $data['consoleHeaders']); $res = $res['body']; $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); @@ -524,7 +520,6 @@ class UsageTest extends Scope return $data; } - /** @depends testDatabaseStats */ public function testPrepareFunctionsStats(array $data): array { @@ -561,17 +556,17 @@ class UsageTest extends Scope $this->assertEquals(201, $response1['headers']['status-code']); $this->assertNotEmpty($response1['body']['$id']); - $code = realpath(__DIR__ . '/../../resources/functions') . "/php/code.tar.gz"; + $code = realpath(__DIR__.'/../../resources/functions').'/php/code.tar.gz'; $this->packageCode('php'); $deployment = $this->client->call( Client::METHOD_POST, - '/functions/' . $functionId . '/deployments', - array_merge($headers, ['content-type' => 'multipart/form-data',]), + '/functions/'.$functionId.'/deployments', + array_merge($headers, ['content-type' => 'multipart/form-data']), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true + 'activate' => true, ] ); @@ -587,7 +582,7 @@ class UsageTest extends Scope $response = $this->client->call( Client::METHOD_PATCH, - '/functions/' . $functionId . '/deployments/' . $deploymentId, + '/functions/'.$functionId.'/deployments/'.$deploymentId, $headers ); @@ -600,7 +595,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_POST, - '/functions/' . $functionId . '/executions', + '/functions/'.$functionId.'/executions', $headers, [ 'async' => false, @@ -621,7 +616,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_POST, - '/functions/' . $functionId . '/executions', + '/functions/'.$functionId.'/executions', $headers, [ 'async' => false, @@ -640,7 +635,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_POST, - '/functions/' . $functionId . '/executions', + '/functions/'.$functionId.'/executions', $headers, [ 'async' => true, @@ -655,7 +650,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_GET, - '/functions/' . $functionId . '/executions/' . $execution['body']['$id'], + '/functions/'.$functionId.'/executions/'.$execution['body']['$id'], $headers ); @@ -686,7 +681,7 @@ class UsageTest extends Scope $response = $this->client->call( Client::METHOD_GET, - '/functions/' . $functionId . '/usage?range=30d', + '/functions/'.$functionId.'/usage?range=30d', $data['consoleHeaders'] ); diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index ee41129fde..7146ebc392 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -13,19 +13,19 @@ trait ProjectCustom protected static $project = []; /** - * @param bool $fresh + * @param bool $fresh * @return array */ public function getProject(bool $fresh = false): array { - if (!empty(self::$project) && !$fresh) { + if (! empty(self::$project) && ! $fresh) { return self::$project; } $team = $this->client->call(Client::METHOD_POST, '/teams', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'teamId' => ID::unique(), @@ -38,7 +38,7 @@ trait ProjectCustom $project = $this->client->call(Client::METHOD_POST, '/projects', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'projectId' => ID::unique(), @@ -52,10 +52,10 @@ trait ProjectCustom $this->assertEquals(201, $project['headers']['status-code']); $this->assertNotEmpty($project['body']); - $key = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/keys', [ + $key = $this->client->call(Client::METHOD_POST, '/projects/'.$project['body']['$id'].'/keys', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'name' => 'Demo Project Key', @@ -92,10 +92,10 @@ trait ProjectCustom $this->assertNotEmpty($key['body']); $this->assertNotEmpty($key['body']['secret']); - $webhook = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/webhooks', [ + $webhook = $this->client->call(Client::METHOD_POST, '/projects/'.$project['body']['$id'].'/webhooks', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'name' => 'Webhook Test', @@ -104,7 +104,7 @@ trait ProjectCustom // 'functions.*', TODO @christyjacob4 : enable test once we allow functions.* events 'buckets.*', 'teams.*', - 'users.*' + 'users.*', ], 'url' => 'http://request-catcher:5000/webhook', 'security' => false, @@ -130,13 +130,12 @@ trait ProjectCustom public function getNewKey(array $scopes) { - $projectId = self::$project['$id']; - $key = $this->client->call(Client::METHOD_POST, '/projects/' . $projectId . '/keys', [ + $key = $this->client->call(Client::METHOD_POST, '/projects/'.$projectId.'/keys', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'name' => 'Demo Project Key', diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 14eb83897b..4eaf846c27 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Scopes; use Appwrite\Tests\Retryable; -use Tests\E2E\Client; use PHPUnit\Framework\TestCase; +use Tests\E2E\Client; use Utopia\Database\Helpers\ID; abstract class Scope extends TestCase @@ -12,6 +12,7 @@ abstract class Scope extends TestCase use Retryable; protected ?Client $client = null; + protected string $endpoint = 'http://localhost/v1'; protected function setUp(): void @@ -72,7 +73,7 @@ abstract class Scope extends TestCase return self::$root; } - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -98,7 +99,7 @@ abstract class Scope extends TestCase 'password' => $password, ]); - $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_console']; + $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_console']; self::$root = [ '$id' => ID::custom($root['body']['$id']), @@ -124,7 +125,7 @@ abstract class Scope extends TestCase return self::$user[$this->getProject()['$id']]; } - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -150,7 +151,7 @@ abstract class Scope extends TestCase 'password' => $password, ]); - $token = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $token = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; self::$user[$this->getProject()['$id']] = [ '$id' => ID::custom($user['body']['$id']), diff --git a/tests/e2e/Scopes/SideClient.php b/tests/e2e/Scopes/SideClient.php index 54f77a9747..2348da8e6b 100644 --- a/tests/e2e/Scopes/SideClient.php +++ b/tests/e2e/Scopes/SideClient.php @@ -8,7 +8,7 @@ trait SideClient { return [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $this->getUser()['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$this->getUser()['session'], ]; } diff --git a/tests/e2e/Scopes/SideConsole.php b/tests/e2e/Scopes/SideConsole.php index 74a0dd0c60..f067977c14 100644 --- a/tests/e2e/Scopes/SideConsole.php +++ b/tests/e2e/Scopes/SideConsole.php @@ -8,8 +8,8 @@ trait SideConsole { return [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], - 'x-appwrite-mode' => 'admin' + 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'x-appwrite-mode' => 'admin', ]; } diff --git a/tests/e2e/Scopes/SideServer.php b/tests/e2e/Scopes/SideServer.php index b5e15150e9..f72ac1f2e2 100644 --- a/tests/e2e/Scopes/SideServer.php +++ b/tests/e2e/Scopes/SideServer.php @@ -12,7 +12,7 @@ trait SideServer public function getHeaders(): array { return [ - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]; } diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 291d55b221..84c32aede9 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -4,15 +4,15 @@ namespace Tests\E2E\Services\Account; use Appwrite\Tests\Retry; use Tests\E2E\Client; -use Utopia\Database\Helpers\ID; use Utopia\Database\DateTime; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; trait AccountBase { public function testCreateAccount(): array { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -126,13 +126,13 @@ trait AccountBase $this->assertNotFalse(\DateTime::createFromFormat('Y-m-d\TH:i:s.uP', $response['body']['expire'])); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; // apiKey is only available in custom client test $apiKey = $this->getProject()['apiKey']; - if (!empty($apiKey)) { + if (! empty($apiKey)) { $userId = $response['body']['userId']; - $response = $this->client->call(Client::METHOD_GET, '/users/' . $userId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$userId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -163,7 +163,7 @@ trait AccountBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $email . 'x', + 'email' => $email.'x', 'password' => $password, ]); @@ -175,7 +175,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], ]), [ 'email' => $email, - 'password' => $password . 'x', + 'password' => $password.'x', ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -213,7 +213,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -237,7 +237,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_GET, '/account', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session . 'xx', + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session.'xx', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -260,7 +260,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -297,7 +297,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -357,7 +357,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -365,7 +365,7 @@ trait AccountBase $this->assertNotEmpty($response['body']['logs']); $this->assertCount(3, $response['body']['logs']); $this->assertIsNumeric($response['body']['total']); - $this->assertContains($response['body']['logs'][1]['event'], ["session.create"]); + $this->assertContains($response['body']['logs'][1]['event'], ['session.create']); $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][1]['time'])); @@ -387,7 +387,7 @@ trait AccountBase $this->assertEquals('--', $response['body']['logs'][1]['countryCode']); $this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']); - $this->assertContains($response['body']['logs'][2]['event'], ["user.create"]); + $this->assertContains($response['body']['logs'][2]['event'], ['user.create']); $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); @@ -413,9 +413,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'queries' => [ 'limit(1)' ], + 'queries' => ['limit(1)'], ]); $this->assertEquals($responseLimit['headers']['status-code'], 200); @@ -430,9 +430,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'queries' => [ 'offset(1)' ], + 'queries' => ['offset(1)'], ]); $this->assertEquals($responseOffset['headers']['status-code'], 200); @@ -447,9 +447,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'queries' => [ 'limit(1)', 'offset(1)' ], + 'queries' => ['limit(1)', 'offset(1)'], ]); $this->assertEquals($responseLimitOffset['headers']['status-code'], 200); @@ -491,9 +491,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'name' => $newName + 'name' => $newName, ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -519,7 +519,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -528,9 +528,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'name' => 'ocSRq1d3QphHivJyUmYY7WMnrxyjdk5YvVwcDqx2zS0coxESN8RmsQwLWw5Whnf0WbVohuFWTRAaoKgCOO0Y0M7LwgFnZmi8881Y72222222222222222222222222222' + 'name' => 'ocSRq1d3QphHivJyUmYY7WMnrxyjdk5YvVwcDqx2zS0coxESN8RmsQwLWw5Whnf0WbVohuFWTRAaoKgCOO0Y0M7LwgFnZmi8881Y72222222222222222222222222222', ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -557,7 +557,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -595,7 +595,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -607,7 +607,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -621,9 +621,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'password' => 'new-password' + 'password' => 'new-password', ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -637,7 +637,7 @@ trait AccountBase */ public function testUpdateAccountEmail($data): array { - $newEmail = uniqid() . 'new@localhost.test'; + $newEmail = uniqid().'new@localhost.test'; $session = $data['session'] ?? ''; /** @@ -647,7 +647,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'email' => $newEmail, 'password' => 'new-password', @@ -675,7 +675,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -691,9 +691,9 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], ]), [ 'userId' => ID::unique(), - 'email' => $data['email'], - 'password' => $data['password'], - 'name' => $data['name'], + 'email' => $data['email'], + 'password' => $data['password'], + 'name' => $data['name'], ]); $this->assertEquals($response['headers']['status-code'], 201); @@ -703,7 +703,6 @@ trait AccountBase $this->assertEquals($response['body']['email'], $data['email']); $this->assertEquals($response['body']['name'], $data['name']); - $data['email'] = $newEmail; return $data; @@ -714,7 +713,7 @@ trait AccountBase */ public function testUpdateAccountPrefs($data): array { - $newEmail = uniqid() . 'new@localhost.test'; + $newEmail = uniqid().'new@localhost.test'; $session = $data['session'] ?? ''; /** @@ -724,12 +723,12 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ] + ], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -753,21 +752,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'prefs' => '{}' - ]); - - $this->assertEquals($response['headers']['status-code'], 400); - - - $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ - 'prefs' => '[]' + 'prefs' => '{}', ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -776,9 +763,20 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'prefs' => '{"test": "value"}' + 'prefs' => '[]', + ]); + + $this->assertEquals($response['headers']['status-code'], 400); + + $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + ]), [ + 'prefs' => '{"test": "value"}', ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -786,29 +784,29 @@ trait AccountBase /** * Prefs size exceeded */ - $prefsObject = ["longValue" => str_repeat("🍰", 100000)]; + $prefsObject = ['longValue' => str_repeat('🍰', 100000)]; $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'prefs' => $prefsObject + 'prefs' => $prefsObject, ]); $this->assertEquals(400, $response['headers']['status-code']); // Now let's test the same thing, but with normal symbol instead of multi-byte cake emoji - $prefsObject = ["longValue" => str_repeat("-", 100000)]; + $prefsObject = ['longValue' => str_repeat('-', 100000)]; $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'prefs' => $prefsObject + 'prefs' => $prefsObject, ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -832,7 +830,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'url' => 'http://localhost/verification', @@ -850,14 +848,14 @@ trait AccountBase $this->assertEquals('Account Verification', $lastEmail['subject']); $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); + $expireTime = strpos($lastEmail['text'], 'expire='.urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -868,7 +866,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'url' => 'localhost/verification', ]); @@ -879,7 +877,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'url' => 'http://remotehost/verification', ]); @@ -907,7 +905,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => $id, 'secret' => $verification, @@ -922,7 +920,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => ID::custom('ewewe'), 'secret' => $verification, @@ -934,7 +932,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => $id, 'secret' => 'sdasdasdasd', @@ -967,7 +965,7 @@ trait AccountBase ]); $sessionNewId = $response['body']['$id']; - $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $sessionNew = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertEquals($response['headers']['status-code'], 201); @@ -975,16 +973,16 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, ]); $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionNewId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -993,7 +991,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -1005,7 +1003,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -1033,14 +1031,14 @@ trait AccountBase 'password' => $password, ]); - $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $sessionNew = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertEquals($response['headers']['status-code'], 201); $response = $this->client->call(Client::METHOD_GET, '/account', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1049,7 +1047,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1061,7 +1059,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_GET, '/account', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1084,7 +1082,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -1115,7 +1113,7 @@ trait AccountBase 'password' => $password, ]); - $data['session'] = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $data['session'] = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; return $data; } @@ -1153,15 +1151,15 @@ trait AccountBase $recovery = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); + $expireTime = strpos($lastEmail['text'], 'expire='.urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -1268,7 +1266,7 @@ trait AccountBase ]), [ 'userId' => $id, 'secret' => $recovery, - 'password' => $newPassowrd . 'x', + 'password' => $newPassowrd.'x', 'passwordAgain' => $newPassowrd, ]); @@ -1279,7 +1277,7 @@ trait AccountBase public function testCreateMagicUrl(): array { - $email = \time() . 'user@appwrite.io'; + $email = \time().'user@appwrite.io'; /** * Test for SUCCESS @@ -1307,15 +1305,15 @@ trait AccountBase $token = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode($response['body']['expire']), 0); + $expireTime = strpos($lastEmail['text'], 'expire='.urlencode($response['body']['expire']), 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -1391,13 +1389,13 @@ trait AccountBase $this->assertNotEmpty($response['body']['userId']); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -1432,7 +1430,6 @@ trait AccountBase $this->assertEquals(401, $response['headers']['status-code']); - $data['sessionId'] = $sessionId; $data['session'] = $session; @@ -1454,9 +1451,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'password' => 'new-password' + 'password' => 'new-password', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -1492,7 +1489,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -1504,7 +1501,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'password' => 'new-password', 'oldPassword' => 'wrong-password', @@ -1518,9 +1515,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'password' => 'new-password' + 'password' => 'new-password', ]); $this->assertEquals($response['headers']['status-code'], 401); diff --git a/tests/e2e/Services/Account/AccountConsoleClientTest.php b/tests/e2e/Services/Account/AccountConsoleClientTest.php index b517d8c408..c1a248ac49 100644 --- a/tests/e2e/Services/Account/AccountConsoleClientTest.php +++ b/tests/e2e/Services/Account/AccountConsoleClientTest.php @@ -3,11 +3,11 @@ namespace Tests\E2E\Services\Account; use Appwrite\Extend\Exception; -use Tests\E2E\Scopes\Scope; +use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectConsole; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; -use Tests\E2E\Client; use Utopia\Database\Validator\Datetime as DatetimeValidator; class AccountConsoleClientTest extends Scope @@ -18,7 +18,7 @@ class AccountConsoleClientTest extends Scope public function testCreateAccountWithInvite(): void { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -34,7 +34,7 @@ class AccountConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'Invalid Code' + 'code' => 'Invalid Code', ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -66,7 +66,7 @@ class AccountConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'code-zero' + 'code' => 'code-zero', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -76,7 +76,7 @@ class AccountConsoleClientTest extends Scope $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $response = $this->client->call(Client::METHOD_POST, '/account/invite', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', @@ -86,7 +86,7 @@ class AccountConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'code-one' + 'code' => 'code-one', ]); $this->assertEquals(201, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index d225496a65..7ca0798a61 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3,18 +3,16 @@ namespace Tests\E2E\Services\Account; use Appwrite\Extend\Exception; -use Appwrite\SMS\Adapter\Mock; use Appwrite\Tests\Retry; +use function sleep; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; -use function sleep; - class AccountCustomClientTest extends Scope { use AccountBase; @@ -23,7 +21,7 @@ class AccountCustomClientTest extends Scope public function testCreateAccountWithInvite(): void { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -40,7 +38,7 @@ class AccountCustomClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'Invalid Code' + 'code' => 'Invalid Code', ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -59,11 +57,11 @@ class AccountCustomClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$this->getProject()['$id'].'/oauth2', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'provider' => $provider, 'appId' => $appId, @@ -73,7 +71,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/'.$provider, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -88,11 +86,11 @@ class AccountCustomClientTest extends Scope /** * Test for Failure when disabled */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$this->getProject()['$id'].'/oauth2', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'provider' => $provider, 'appId' => $appId, @@ -102,7 +100,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/'.$provider, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -118,7 +116,7 @@ class AccountCustomClientTest extends Scope public function testBlockedAccount(): array { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name (blocked)'; @@ -152,18 +150,18 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 201); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $id . '/status', [ + $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$id.'/status', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -177,7 +175,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 401); @@ -196,10 +194,9 @@ class AccountCustomClientTest extends Scope return []; } - public function testSelfBlockedAccount(): array { - $email = uniqid() . 'user55@localhost.test'; + $email = uniqid().'user55@localhost.test'; $password = 'password'; $name = 'User Name (self blocked)'; @@ -232,13 +229,13 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 201); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -246,20 +243,20 @@ class AccountCustomClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/account/status', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ], [ 'status' => false, ]); $this->assertEquals($response['headers']['status-code'], 200); - $this->assertStringContainsString('a_session_' . $this->getProject()['$id'] . '=deleted', $response['headers']['set-cookie']); + $this->assertStringContainsString('a_session_'.$this->getProject()['$id'].'=deleted', $response['headers']['set-cookie']); $this->assertEquals('[]', $response['headers']['x-fallback-cookies']); $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 401); @@ -280,7 +277,7 @@ class AccountCustomClientTest extends Scope public function testCreateJWT(): array { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name (JWT)'; @@ -314,13 +311,13 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 201); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -329,7 +326,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 201); @@ -357,11 +354,11 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -394,13 +391,13 @@ class AccountCustomClientTest extends Scope $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; \usleep(1000 * 30); // wait for 30ms to let the shutdown update accessedAt $apiKey = $this->getProject()['apiKey']; $userId = $response['body']['userId']; - $response = $this->client->call(Client::METHOD_GET, '/users/' . $userId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$userId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -417,7 +414,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -437,7 +434,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'oldPassword' => '', ]); @@ -452,7 +449,7 @@ class AccountCustomClientTest extends Scope */ public function testUpdateAnonymousAccountEmail($session) { - $email = uniqid() . 'new@localhost.test'; + $email = uniqid().'new@localhost.test'; /** * Test for FAILURE @@ -461,7 +458,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'email' => $email, 'password' => '', @@ -475,7 +472,7 @@ class AccountCustomClientTest extends Scope public function testConvertAnonymousAccount() { $session = $this->testCreateAnonymousAccount(); - $email = uniqid() . 'new@localhost.test'; + $email = uniqid().'new@localhost.test'; $password = 'new-password'; /** @@ -488,14 +485,14 @@ class AccountCustomClientTest extends Scope ]), [ 'userId' => ID::unique(), 'email' => $email, - 'password' => $password + 'password' => $password, ]); $response = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'email' => $email, 'password' => $password, @@ -506,13 +503,13 @@ class AccountCustomClientTest extends Scope /** * Test for SUCCESS */ - $email = uniqid() . 'new@localhost.test'; + $email = uniqid().'new@localhost.test'; $response = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'email' => $email, 'password' => $password, @@ -540,12 +537,11 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'url' => 'http://localhost' + 'url' => 'http://localhost', ]); - $this->assertEquals($response['headers']['status-code'], 201); return []; @@ -565,18 +561,18 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); $userId = $response['body']['$id'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$this->getProject()['$id'].'/oauth2', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'provider' => $provider, 'appId' => $appId, @@ -586,17 +582,17 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/'.$provider, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'success' => 'http://localhost/v1/mock/tests/general/oauth2/success', 'failure' => 'http://localhost/v1/mock/tests/general/oauth2/failure', ]); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('success', $response['body']['result']); @@ -605,7 +601,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -621,7 +617,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals(200, $response['headers']['status-code']); @@ -637,7 +633,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals(200, $response['headers']['status-code']); @@ -656,7 +652,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -664,11 +660,11 @@ class AccountCustomClientTest extends Scope $sessionID = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/' . $sessionID, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/'.$sessionID, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -678,7 +674,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 404); @@ -741,7 +737,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'search' => '"' . $email . '"', + 'search' => '"'.$email.'"', ]); @@ -766,7 +762,6 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['body']['users'][0]['email'], $email); } - public function testCreatePhone(): array { $number = '+123456789'; @@ -798,7 +793,7 @@ class AccountCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'userId' => ID::unique() + 'userId' => ID::unique(), ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -874,13 +869,13 @@ class AccountCustomClientTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['userId']); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -915,19 +910,19 @@ class AccountCustomClientTest extends Scope public function testConvertPhoneToPassword(array $data): array { $session = $data['session']; - $email = uniqid() . 'new@localhost.test'; + $email = uniqid().'new@localhost.test'; $password = 'new-password'; /** * Test for SUCCESS */ - $email = uniqid() . 'new@localhost.test'; + $email = uniqid().'new@localhost.test'; $response = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'email' => $email, 'password' => $password, @@ -969,10 +964,10 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'phone' => $newPhone, - 'password' => 'new-password' + 'password' => 'new-password', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -997,7 +992,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -1022,7 +1017,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); @@ -1036,7 +1031,7 @@ class AccountCustomClientTest extends Scope $smsRequest = $this->getLastRequest(); return \array_merge($data, [ - 'token' => $smsRequest['data']['message'] + 'token' => $smsRequest['data']['message'], ]); } @@ -1056,7 +1051,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => $id, 'secret' => $secret, @@ -1071,7 +1066,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => ID::custom('ewewe'), 'secret' => $secret, @@ -1083,7 +1078,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => $id, 'secret' => '999999', diff --git a/tests/e2e/Services/Account/AccountCustomServerTest.php b/tests/e2e/Services/Account/AccountCustomServerTest.php index 143277608d..6c6c2df654 100644 --- a/tests/e2e/Services/Account/AccountCustomServerTest.php +++ b/tests/e2e/Services/Account/AccountCustomServerTest.php @@ -15,7 +15,7 @@ class AccountCustomServerTest extends Scope public function testCreateAccount(): array { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; diff --git a/tests/e2e/Services/Avatars/AvatarsBase.php b/tests/e2e/Services/Avatars/AvatarsBase.php index e2ddc1a863..a7518d38af 100644 --- a/tests/e2e/Services/Avatars/AvatarsBase.php +++ b/tests/e2e/Services/Avatars/AvatarsBase.php @@ -45,7 +45,6 @@ trait AvatarsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/avatars/credit-cards/unknown', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -108,7 +107,6 @@ trait AvatarsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/avatars/browsers/unknown', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -262,7 +260,7 @@ trait AvatarsBase $response = $this->client->call(Client::METHOD_GET, '/avatars/image', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'url' => 'invalid://appwrite.io/images/apple.png' + 'url' => 'invalid://appwrite.io/images/apple.png', ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -349,7 +347,7 @@ trait AvatarsBase $this->assertEquals(400, $image->getImageWidth()); $this->assertEquals(400, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-default.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-default.png')), strlen($response['body'])); $response = $this->client->call(Client::METHOD_GET, '/avatars/qr', [ 'x-appwrite-project' => $this->getProject()['$id'], @@ -367,7 +365,7 @@ trait AvatarsBase $this->assertEquals(200, $image->getImageWidth()); $this->assertEquals(200, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-size-200.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-size-200.png')), strlen($response['body'])); $response = $this->client->call(Client::METHOD_GET, '/avatars/qr', [ 'x-appwrite-project' => $this->getProject()['$id'], @@ -386,7 +384,7 @@ trait AvatarsBase $this->assertEquals(200, $image->getImageWidth()); $this->assertEquals(200, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); $response = $this->client->call(Client::METHOD_GET, '/avatars/qr', [ 'x-appwrite-project' => $this->getProject()['$id'], @@ -402,7 +400,7 @@ trait AvatarsBase $this->assertEquals(200, $image->getImageWidth()); $this->assertEquals(200, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('attachment; filename="qr.png"', $response['headers']['content-disposition']); @@ -448,7 +446,6 @@ trait AvatarsBase return []; } - public function testGetInitials() { /** @@ -529,11 +526,11 @@ trait AvatarsBase $image = new \Imagick(); $image->readImageBlob($response['body']); - $original = new \Imagick(__DIR__ . '/../../../resources/initials.png'); + $original = new \Imagick(__DIR__.'/../../../resources/initials.png'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/initials.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/initials.png')), strlen($response['body'])); } } diff --git a/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php b/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php index a59d694114..bfd17ef1e9 100644 --- a/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php +++ b/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Avatars; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; class AvatarsConsoleClientTest extends Scope diff --git a/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php b/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php index dc399971a0..edf09d5ba1 100644 --- a/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php +++ b/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Avatars; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; class AvatarsCustomClientTest extends Scope diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index c2c1c70bd6..9bc081d2ab 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -5,12 +5,11 @@ namespace Tests\E2E\Services\Databases; use Appwrite\Extend\Exception; use Tests\E2E\Client; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; trait DatabasesBase @@ -23,10 +22,10 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'databaseId' => ID::unique(), - 'name' => 'Test Database' + 'name' => 'Test Database', ]); $this->assertNotEmpty($database['body']['$id']); @@ -45,10 +44,10 @@ trait DatabasesBase /** * Test for SUCCESS */ - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -61,10 +60,10 @@ trait DatabasesBase $this->assertEquals(201, $movies['headers']['status-code']); $this->assertEquals($movies['body']['name'], 'Movies'); - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -93,10 +92,10 @@ trait DatabasesBase /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Movies', 'enabled' => false, @@ -107,7 +106,7 @@ trait DatabasesBase $this->assertFalse($response['body']['enabled']); if ($this->getSide() === 'client') { - $responseCreateDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $responseCreateDocument = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -124,14 +123,14 @@ trait DatabasesBase $this->assertEquals(404, $responseCreateDocument['headers']['status-code']); - $responseListDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $responseListDocument = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $responseListDocument['headers']['status-code']); - $responseGetDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/someID', array_merge([ + $responseGetDocument = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/someID', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -139,10 +138,10 @@ trait DatabasesBase $this->assertEquals(404, $responseGetDocument['headers']['status-code']); } - $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Movies', 'enabled' => true, @@ -160,20 +159,20 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ + $title = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $description = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ + $description = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'description', 'size' => 512, @@ -181,10 +180,10 @@ trait DatabasesBase 'default' => '', ]); - $tagline = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ + $tagline = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'tagline', 'size' => 512, @@ -192,10 +191,10 @@ trait DatabasesBase 'default' => '', ]); - $releaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([ + $releaseYear = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'releaseYear', 'required' => true, @@ -203,20 +202,20 @@ trait DatabasesBase 'max' => 2200, ]); - $duration = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([ + $duration = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'duration', 'required' => false, 'min' => 60, ]); - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'actors', 'size' => 256, @@ -224,25 +223,25 @@ trait DatabasesBase 'array' => true, ]); - $datetime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/datetime', array_merge([ + $datetime = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'birthDay', 'required' => false, ]); - $relationship = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/relationship', array_merge([ + $relationship = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'starringActors', - 'twoWayKey' => 'movie' + 'twoWayKey' => 'movie', ]); $this->assertEquals(202, $title['headers']['status-code']); @@ -298,10 +297,10 @@ trait DatabasesBase // wait for database worker to create attributes sleep(2); - $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ + $movies = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertIsArray($movies['body']['attributes']); @@ -324,7 +323,7 @@ trait DatabasesBase public function testListAttributes(array $data): void { $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -333,7 +332,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, \count($response['body']['attributes'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -350,10 +349,10 @@ trait DatabasesBase public function testAttributeResponseModels(array $data): array { $databaseId = $data['databaseId']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Response Models', @@ -366,12 +365,12 @@ trait DatabasesBase $collectionId = $collection['body']['$id']; - $attributesPath = "/databases/" . $databaseId . "/collections/{$collectionId}/attributes"; + $attributesPath = '/databases/'.$databaseId."/collections/{$collectionId}/attributes"; - $string = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ + $string = $this->client->call(Client::METHOD_POST, $attributesPath.'/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'string', 'size' => 16, @@ -379,20 +378,20 @@ trait DatabasesBase 'default' => 'default', ]); - $email = $this->client->call(Client::METHOD_POST, $attributesPath . '/email', array_merge([ + $email = $this->client->call(Client::METHOD_POST, $attributesPath.'/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'email', 'required' => false, 'default' => 'default@example.com', ]); - $enum = $this->client->call(Client::METHOD_POST, $attributesPath . '/enum', array_merge([ + $enum = $this->client->call(Client::METHOD_POST, $attributesPath.'/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'enum', 'elements' => ['yes', 'no', 'maybe'], @@ -400,80 +399,80 @@ trait DatabasesBase 'default' => 'maybe', ]); - $ip = $this->client->call(Client::METHOD_POST, $attributesPath . '/ip', array_merge([ + $ip = $this->client->call(Client::METHOD_POST, $attributesPath.'/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'ip', 'required' => false, 'default' => '192.0.2.0', ]); - $url = $this->client->call(Client::METHOD_POST, $attributesPath . '/url', array_merge([ + $url = $this->client->call(Client::METHOD_POST, $attributesPath.'/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'url', 'required' => false, 'default' => 'http://example.com', ]); - $integer = $this->client->call(Client::METHOD_POST, $attributesPath . '/integer', array_merge([ + $integer = $this->client->call(Client::METHOD_POST, $attributesPath.'/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'integer', 'required' => false, 'min' => 1, 'max' => 5, - 'default' => 3 + 'default' => 3, ]); - $float = $this->client->call(Client::METHOD_POST, $attributesPath . '/float', array_merge([ + $float = $this->client->call(Client::METHOD_POST, $attributesPath.'/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'float', 'required' => false, 'min' => 1.5, 'max' => 5.5, - 'default' => 3.5 + 'default' => 3.5, ]); - $boolean = $this->client->call(Client::METHOD_POST, $attributesPath . '/boolean', array_merge([ + $boolean = $this->client->call(Client::METHOD_POST, $attributesPath.'/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'boolean', 'required' => false, 'default' => true, ]); - $datetime = $this->client->call(Client::METHOD_POST, $attributesPath . '/datetime', array_merge([ + $datetime = $this->client->call(Client::METHOD_POST, $attributesPath.'/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'datetime', 'required' => false, 'default' => null, ]); - $relationship = $this->client->call(Client::METHOD_POST, $attributesPath . '/relationship', array_merge([ + $relationship = $this->client->call(Client::METHOD_POST, $attributesPath.'/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'relationship', - 'twoWayKey' => 'twoWayKey' + 'twoWayKey' => 'twoWayKey', ]); $this->assertEquals(202, $string['headers']['status-code']); @@ -563,64 +562,64 @@ trait DatabasesBase // Wait for database worker to create attributes sleep(5); - $stringResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $string['body']['key'], array_merge([ + $stringResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$string['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $emailResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $email['body']['key'], array_merge([ + $emailResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$email['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $enumResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $enum['body']['key'], array_merge([ + $enumResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$enum['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $ipResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $ip['body']['key'], array_merge([ + $ipResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$ip['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $urlResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $url['body']['key'], array_merge([ + $urlResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$url['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $integerResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $integer['body']['key'], array_merge([ + $integerResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$integer['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $floatResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $float['body']['key'], array_merge([ + $floatResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$float['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $booleanResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $boolean['body']['key'], array_merge([ + $booleanResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$boolean['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $datetimeResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $datetime['body']['key'], array_merge([ + $datetimeResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$datetime['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $relationshipResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $relationship['body']['key'], array_merge([ + $relationshipResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$relationship['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $stringResponse['headers']['status-code']); @@ -716,10 +715,10 @@ trait DatabasesBase $this->assertEquals($relationship['body']['twoWay'], $relationshipResponse['body']['twoWay']); $this->assertEquals($relationship['body']['twoWayKey'], $relationshipResponse['body']['twoWayKey']); - $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes', array_merge([ + $attributes = $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'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $attributes['headers']['status-code']); @@ -812,10 +811,10 @@ trait DatabasesBase $this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']); $this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -911,10 +910,10 @@ trait DatabasesBase /** * Test for FAILURE */ - $badEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ + $badEnum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'enum', 'elements' => ['yes', 'no', ''], @@ -935,10 +934,10 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - $titleIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $titleIndex = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'titleIndex', 'type' => 'fulltext', @@ -951,10 +950,10 @@ trait DatabasesBase $this->assertCount(1, $titleIndex['body']['attributes']); $this->assertEquals('title', $titleIndex['body']['attributes'][0]); - $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'releaseYear', 'type' => 'key', @@ -967,10 +966,10 @@ trait DatabasesBase $this->assertCount(1, $releaseYearIndex['body']['attributes']); $this->assertEquals('releaseYear', $releaseYearIndex['body']['attributes'][0]); - $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'releaseYearDated', 'type' => 'key', @@ -988,10 +987,10 @@ trait DatabasesBase // wait for database worker to create index sleep(2); - $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ + $movies = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); $this->assertIsArray($movies['body']['indexes']); @@ -1003,10 +1002,10 @@ trait DatabasesBase $this->assertEquals('available', $movies['body']['indexes'][1]['status']); $this->assertEquals('available', $movies['body']['indexes'][2]['status']); - $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'birthDay', 'type' => 'key', @@ -1020,10 +1019,10 @@ trait DatabasesBase $this->assertEquals('birthDay', $releaseWithDate['body']['attributes'][0]); // Test for failure - $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'releaseYearDated', 'type' => 'fulltext', @@ -1033,10 +1032,10 @@ trait DatabasesBase $this->assertEquals(400, $fulltextReleaseYear['headers']['status-code']); $this->assertEquals($fulltextReleaseYear['body']['message'], 'Attribute "releaseYear" cannot be part of a FULLTEXT index, must be of type string'); - $noAttributes = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $noAttributes = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'none', 'type' => 'key', @@ -1046,10 +1045,10 @@ trait DatabasesBase $this->assertEquals(400, $noAttributes['headers']['status-code']); $this->assertEquals($noAttributes['body']['message'], 'No attributes provided for index'); - $duplicates = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $duplicates = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'duplicate', 'type' => 'fulltext', @@ -1059,7 +1058,7 @@ trait DatabasesBase $this->assertEquals(400, $duplicates['headers']['status-code']); $this->assertEquals($duplicates['body']['message'], 'Duplicate attributes provided'); - $tooLong = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $tooLong = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1081,7 +1080,7 @@ trait DatabasesBase public function testListIndexes(array $data): void { $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1090,7 +1089,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, \count($response['body']['indexes'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1107,7 +1106,7 @@ trait DatabasesBase public function testCreateDocument(array $data): array { $databaseId = $data['databaseId']; - $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1119,16 +1118,16 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ] + ], ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1141,16 +1140,16 @@ trait DatabasesBase 'Tom Holland', 'Zendaya Maree Stoermer', 'Samuel Jackson', - ] + ], ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); - $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1169,10 +1168,10 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); - $document4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document4 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1184,7 +1183,7 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals(201, $document1['headers']['status-code']); @@ -1232,7 +1231,7 @@ trait DatabasesBase $this->assertEquals(400, $document4['headers']['status-code']); // Delete document 4 with incomplete path - $this->assertEquals(404, $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/', array_merge([ + $this->assertEquals(404, $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()))['headers']['status-code']); @@ -1246,7 +1245,7 @@ trait DatabasesBase public function testListDocuments(array $data): array { $databaseId = $data['databaseId']; - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1268,7 +1267,7 @@ trait DatabasesBase $this->assertEquals($databaseId, $document['$databaseId']); } - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1290,10 +1289,10 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'databaseId' => ID::custom('default'), - 'name' => 'Default' + 'name' => 'Default', ]); $this->assertNotEmpty($database['body']['$id']); @@ -1302,11 +1301,10 @@ trait DatabasesBase /** * Test for SUCCESS */ - $movies = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -1328,8 +1326,7 @@ trait DatabasesBase /** * Test for SUCCESS */ - - $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1347,7 +1344,7 @@ trait DatabasesBase { $databaseId = $data['databaseId']; foreach ($data['documents'] as $document) { - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$document['$collectionId'].'/documents/'.$document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1373,7 +1370,7 @@ trait DatabasesBase $databaseId = $data['databaseId']; $document = $data['documents'][0]; - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$document['$collectionId'].'/documents/'.$document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1397,7 +1394,7 @@ trait DatabasesBase /** * Test after without order. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1408,11 +1405,11 @@ trait DatabasesBase $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['documents'][0]['$id'] . '")'], + 'queries' => ['cursorAfter("'.$base['body']['documents'][0]['$id'].'")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1420,11 +1417,11 @@ trait DatabasesBase $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][1]['$id']); $this->assertCount(2, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['documents'][2]['$id'] . '")'], + 'queries' => ['cursorAfter("'.$base['body']['documents'][2]['$id'].'")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1433,7 +1430,7 @@ trait DatabasesBase /** * Test with ASC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1446,11 +1443,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")'], + 'queries' => ['cursorAfter("'.$base['body']['documents'][1]['$id'].'")', 'orderAsc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1460,7 +1457,7 @@ trait DatabasesBase /** * Test with DESC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1473,11 +1470,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")'], + 'queries' => ['cursorAfter("'.$base['body']['documents'][1]['$id'].'")', 'orderDesc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1487,7 +1484,7 @@ trait DatabasesBase /** * Test after with unknown document. */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1508,7 +1505,7 @@ trait DatabasesBase /** * Test before without order. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1519,11 +1516,11 @@ trait DatabasesBase $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['documents'][2]['$id'] . '")'], + 'queries' => ['cursorBefore("'.$base['body']['documents'][2]['$id'].'")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1531,11 +1528,11 @@ trait DatabasesBase $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][1]['$id']); $this->assertCount(2, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['documents'][0]['$id'] . '")'], + 'queries' => ['cursorBefore("'.$base['body']['documents'][0]['$id'].'")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1544,7 +1541,7 @@ trait DatabasesBase /** * Test with ASC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1557,11 +1554,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")'], + 'queries' => ['cursorBefore("'.$base['body']['documents'][1]['$id'].'")', 'orderAsc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1571,7 +1568,7 @@ trait DatabasesBase /** * Test with DESC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1584,11 +1581,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")'], + 'queries' => ['cursorBefore("'.$base['body']['documents'][1]['$id'].'")', 'orderDesc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1604,7 +1601,7 @@ trait DatabasesBase public function testListDocumentsLimitAndOffset(array $data): array { $databaseId = $data['databaseId']; - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1615,7 +1612,7 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1636,7 +1633,7 @@ trait DatabasesBase public function testDocumentsListQueries(array $data): array { $databaseId = $data['databaseId']; - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1647,18 +1644,18 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("$id", "' . $documents['body']['documents'][0]['$id'] . '")'], + 'queries' => ['equal("$id", "'.$documents['body']['documents'][0]['$id'].'")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1669,7 +1666,7 @@ trait DatabasesBase $this->assertEquals(2017, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1681,7 +1678,7 @@ trait DatabasesBase $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); $this->assertCount(2, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1691,7 +1688,7 @@ trait DatabasesBase $this->assertCount(1, $documents['body']['documents']); $this->assertEquals('Captain America', $documents['body']['documents'][0]['title']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1702,7 +1699,7 @@ trait DatabasesBase $this->assertEquals('Spider-Man: Far From Home', $documents['body']['documents'][0]['title']); $this->assertEquals('Spider-Man: Homecoming', $documents['body']['documents'][1]['title']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1711,7 +1708,7 @@ trait DatabasesBase $this->assertCount(3, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1720,7 +1717,7 @@ trait DatabasesBase $this->assertCount(0, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1728,7 +1725,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1749,11 +1746,11 @@ trait DatabasesBase $conditions[] = $i; } - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("releaseYear", [' . implode(',', $conditions) . '])'], + 'queries' => ['equal("releaseYear", ['.implode(',', $conditions).'])'], ]); $this->assertEquals(400, $documents['headers']['status-code']); @@ -1761,19 +1758,19 @@ trait DatabasesBase $conditions = []; for ($i = 0; $i < 101; $i++) { - $conditions[] = "[" . $i . "] Too long title to cross 2k chars query limit"; + $conditions[] = '['.$i.'] Too long title to cross 2k chars query limit'; } - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['search("title", ' . implode(',', $conditions) . ')'], + 'queries' => ['search("title", '.implode(',', $conditions).')'], ]); $this->assertEquals(400, $documents['headers']['status-code']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1791,7 +1788,7 @@ trait DatabasesBase public function testUpdateDocument(array $data): array { $databaseId = $data['databaseId']; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1801,7 +1798,7 @@ trait DatabasesBase 'releaseYear' => 2017, 'birthDay' => '1976-06-12 14:12:55', 'actors' => [], - '$createdAt' => 5 // Should be ignored + '$createdAt' => 5, // Should be ignored ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), @@ -1825,7 +1822,7 @@ trait DatabasesBase $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1850,7 +1847,7 @@ trait DatabasesBase $this->assertContains(Permission::update(Role::users()), $document['body']['$permissions']); $this->assertContains(Permission::delete(Role::users()), $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1864,7 +1861,7 @@ trait DatabasesBase $this->assertEquals($document['body']['title'], 'Thor: Ragnarok'); $this->assertEquals($document['body']['releaseYear'], 2017); - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-timestamp' => DateTime::formatTz(DateTime::now()), @@ -1879,8 +1876,7 @@ trait DatabasesBase /** * Test for failure */ - - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-timestamp' => 'invalid', @@ -1894,7 +1890,7 @@ trait DatabasesBase $this->assertEquals('Invalid X-Appwrite-Timestamp header value', $response['body']['message']); $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-timestamp' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -1000)), @@ -1917,7 +1913,7 @@ trait DatabasesBase public function testDeleteDocument(array $data): array { $databaseId = $data['databaseId']; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1932,28 +1928,28 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); $id = $document['body']['$id']; $this->assertEquals(201, $document['headers']['status-code']); - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $document['headers']['status-code']); - $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $document['headers']['status-code']); - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1968,7 +1964,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'InvalidDocumentDatabase', @@ -1977,10 +1973,10 @@ trait DatabasesBase $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'invalidDocumentStructure', @@ -1996,48 +1992,48 @@ trait DatabasesBase $collectionId = $collection['body']['$id']; - $email = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email', array_merge([ + $email = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'email', 'required' => false, ]); - $enum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ + $enum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'enum', 'elements' => ['yes', 'no', 'maybe'], 'required' => false, ]); - $ip = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip', array_merge([ + $ip = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'ip', 'required' => false, ]); - $url = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url', array_merge([ + $url = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'url', 'size' => 256, 'required' => false, ]); - $range = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $range = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'range', 'required' => false, @@ -2046,10 +2042,10 @@ trait DatabasesBase ]); // TODO@kodumbeats min and max are rounded in error message - $floatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float', array_merge([ + $floatRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'floatRange', 'required' => false, @@ -2057,10 +2053,10 @@ trait DatabasesBase 'max' => 1.4, ]); - $probability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float', array_merge([ + $probability = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'probability', 'required' => false, @@ -2069,20 +2065,20 @@ trait DatabasesBase 'max' => 1, ]); - $upperBound = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $upperBound = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'upperBound', 'required' => false, 'max' => 10, ]); - $lowerBound = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $lowerBound = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'lowerBound', 'required' => false, @@ -2092,10 +2088,9 @@ trait DatabasesBase /** * Test for failure */ - - $invalidRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $invalidRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'invalidRange', 'required' => false, @@ -2103,9 +2098,9 @@ trait DatabasesBase 'max' => 3, ]); - $defaultArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $defaultArray = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'defaultArray', 'required' => false, @@ -2113,54 +2108,54 @@ trait DatabasesBase 'array' => true, ]); - $defaultRequired = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $defaultRequired = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'attributeId' => ID::custom('defaultRequired'), 'required' => true, - 'default' => 12 + 'default' => 12, ]); - $enumDefault = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ + $enumDefault = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'attributeId' => ID::custom('enumDefault'), 'elements' => ['north', 'west'], - 'default' => 'south' + 'default' => 'south', ]); - $enumDefaultStrict = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ + $enumDefaultStrict = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'attributeId' => ID::custom('enumDefault'), 'elements' => ['north', 'west'], - 'default' => 'NORTH' + 'default' => 'NORTH', ]); - $goodDatetime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([ + $goodDatetime = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'birthDay', 'required' => false, - 'default' => null + 'default' => null, ]); - $datetimeDefault = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([ + $datetimeDefault = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'badBirthDay', 'required' => false, - 'default' => 'bad' + 'default' => 'bad', ]); $this->assertEquals(202, $email['headers']['status-code']); @@ -2184,7 +2179,7 @@ trait DatabasesBase // wait for worker to add attributes sleep(3); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -2195,8 +2190,7 @@ trait DatabasesBase /** * Test for successful validation */ - - $goodEmail = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodEmail = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2208,10 +2202,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $goodEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodEnum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2223,10 +2217,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $goodIp = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodIp = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2238,10 +2232,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $goodUrl = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodUrl = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2253,10 +2247,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $goodRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2268,10 +2262,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $goodFloatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodFloatRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2283,10 +2277,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $goodProbability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $goodProbability = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2298,10 +2292,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $notTooHigh = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $notTooHigh = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2313,10 +2307,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $notTooLow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $notTooLow = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2328,7 +2322,7 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); $this->assertEquals(201, $goodEmail['headers']['status-code']); @@ -2345,7 +2339,7 @@ trait DatabasesBase * Test that custom validators reject documents */ - $badEmail = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badEmail = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2357,10 +2351,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badEnum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2372,10 +2366,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badIp = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badIp = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2387,10 +2381,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badUrl = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badUrl = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2402,10 +2396,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2417,10 +2411,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badFloatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badFloatRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2432,10 +2426,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badProbability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badProbability = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2447,10 +2441,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $tooHigh = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $tooHigh = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2462,10 +2456,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $tooLow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $tooLow = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2477,10 +2471,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); - $badTime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $badTime = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2488,8 +2482,8 @@ trait DatabasesBase 'data' => [ 'birthDay' => '2020-10-10 27:30:10+01:00', ], - 'read' => ['user:' . $this->getUser()['$id']], - 'write' => ['user:' . $this->getUser()['$id']], + 'read' => ['user:'.$this->getUser()['$id']], + 'write' => ['user:'.$this->getUser()['$id']], ]); $this->assertEquals(400, $badEmail['headers']['status-code']); @@ -2519,7 +2513,7 @@ trait DatabasesBase public function testDefaultPermissions(array $data): array { $databaseId = $data['databaseId']; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2552,7 +2546,7 @@ trait DatabasesBase // Updated Permissions - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2563,7 +2557,7 @@ trait DatabasesBase ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), - Permission::update(Role::user($this->getUser()['$id'])) + Permission::update(Role::user($this->getUser()['$id'])), ], ]); @@ -2580,7 +2574,7 @@ trait DatabasesBase Permission::update(Role::user($this->getUser()['$id'])), ], $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2597,7 +2591,7 @@ trait DatabasesBase // Reset Permissions - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2616,7 +2610,7 @@ trait DatabasesBase $this->assertEquals([], $document['body']['$permissions']); // Check client side can no longer read the document. - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2638,7 +2632,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'EnforceCollectionAndDocumentPermissions', @@ -2648,10 +2642,10 @@ trait DatabasesBase $databaseId = $database['body']['$id']; $user = $this->getUser()['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'enforceCollectionAndDocumentPermissions', @@ -2672,10 +2666,10 @@ trait DatabasesBase sleep(2); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'attribute', 'size' => 64, @@ -2688,10 +2682,10 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'key_attribute', 'type' => 'key', @@ -2704,7 +2698,7 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2716,12 +2710,12 @@ trait DatabasesBase Permission::read(Role::user($user)), Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ] + ], ]); $this->assertEquals(201, $document1['headers']['status-code']); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2732,15 +2726,15 @@ trait DatabasesBase 'permissions' => [ Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ] + ], ]); $this->assertEquals(201, $document2['headers']['status-code']); - $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $document3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'documentId' => ID::unique(), 'data' => [ @@ -2754,7 +2748,7 @@ trait DatabasesBase $this->assertEquals(201, $document3['headers']['status-code']); - $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2763,7 +2757,7 @@ trait DatabasesBase $this->assertEquals(3, $documentsUser1['body']['total']); $this->assertCount(3, $documentsUser1['body']['documents']); - $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ + $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2771,7 +2765,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(200, $document3GetWithCollectionRead['headers']['status-code']); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; $this->client->call(Client::METHOD_POST, '/account', [ @@ -2792,33 +2786,33 @@ trait DatabasesBase 'email' => $email, 'password' => $password, ]); - $session2 = $this->client->parseCookie((string)$session2['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session2 = $this->client->parseCookie((string) $session2['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; - $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], [ + $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, ]); // Current user has no collection permissions but has read permission for this document $this->assertEquals(200, $document3GetWithDocumentRead['headers']['status-code']); - $document2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document2['body']['$id'], [ + $document2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document2['body']['$id'], [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, ]); // Current user has no collection or document permissions for this document $this->assertEquals(404, $document2GetFailure['headers']['status-code']); - $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, ]); // Current user has no collection permissions but has read permission for one document @@ -2831,7 +2825,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'EnforceCollectionPermissions', @@ -2841,10 +2835,10 @@ trait DatabasesBase $databaseId = $database['body']['$id']; $user = $this->getUser()['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'enforceCollectionPermissions', @@ -2864,10 +2858,10 @@ trait DatabasesBase sleep(2); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'attribute', 'size' => 64, @@ -2880,10 +2874,10 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'key_attribute', 'type' => 'key', @@ -2896,7 +2890,7 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2908,12 +2902,12 @@ trait DatabasesBase Permission::read(Role::user($user)), Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ] + ], ]); $this->assertEquals(201, $document1['headers']['status-code']); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2924,15 +2918,15 @@ trait DatabasesBase 'permissions' => [ Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ] + ], ]); $this->assertEquals(201, $document2['headers']['status-code']); - $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $document3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'documentId' => ID::unique(), 'data' => [ @@ -2946,7 +2940,7 @@ trait DatabasesBase $this->assertEquals(201, $document3['headers']['status-code']); - $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2955,7 +2949,7 @@ trait DatabasesBase $this->assertEquals(3, $documentsUser1['body']['total']); $this->assertCount(3, $documentsUser1['body']['documents']); - $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ + $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2963,7 +2957,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(200, $document3GetWithCollectionRead['headers']['status-code']); - $email = uniqid() . 'user2@localhost.test'; + $email = uniqid().'user2@localhost.test'; $password = 'password'; $name = 'User Name'; $this->client->call(Client::METHOD_POST, '/account', [ @@ -2984,43 +2978,43 @@ trait DatabasesBase 'email' => $email, 'password' => $password, ]); - $session2 = $this->client->parseCookie((string)$session2['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session2 = $this->client->parseCookie((string) $session2['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; - $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], [ + $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, ]); // Current user has no collection permissions and document permissions are disabled $this->assertEquals(404, $document3GetWithDocumentRead['headers']['status-code']); - $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, ]); // Current user has no collection permissions and document permissions are disabled $this->assertEquals(404, $documentsUser2['headers']['status-code']); // Enable document permissions - $collection = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, [ + $collection = $this->client->call(CLient::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$collectionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'name' => $collection['body']['name'], 'documentSecurity' => true, ]); - $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, ]); // Current user has no collection permissions read access to one document @@ -3034,10 +3028,10 @@ trait DatabasesBase public function testUniqueIndexDuplicate(array $data): array { $databaseId = $data['databaseId']; - $uniqueIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $uniqueIndex = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'unique_title', 'type' => 'unique', @@ -3049,7 +3043,7 @@ trait DatabasesBase sleep(2); // test for failure - $duplicate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $duplicate = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3060,19 +3054,19 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ] + ], ], 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); $this->assertEquals(409, $duplicate['headers']['status-code']); // Test for exception when updating document to conflict - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3083,19 +3077,19 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ] + ], ], 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); $this->assertEquals(201, $document['headers']['status-code']); // Test for exception when updating document to conflict - $duplicate = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $document['body']['$id'], array_merge([ + $duplicate = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3106,13 +3100,13 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ] + ], ], 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); $this->assertEquals(409, $duplicate['headers']['status-code']); @@ -3131,15 +3125,15 @@ trait DatabasesBase ], $this->getHeaders()) : [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents', $headers, [ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$data['databaseId'].'/collections/'.$data['moviesId'].'/documents', $headers, [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Creation Date Test', - 'releaseYear' => 2000 - ] + 'releaseYear' => 2000, + ], ]); $this->assertEquals($document['body']['title'], 'Creation Date Test'); @@ -3150,10 +3144,10 @@ trait DatabasesBase \sleep(1); - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$data['databaseId'].'/collections/'.$data['moviesId'].'/documents/'.$documentId, $headers, [ 'data' => [ 'title' => 'Updated Date Test', - ] + ], ]); $updatedAtSecond = $document['body']['$updatedAt']; @@ -3164,12 +3158,12 @@ trait DatabasesBase \sleep(1); - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$data['databaseId'].'/collections/'.$data['moviesId'].'/documents/'.$documentId, $headers, [ 'data' => [ 'title' => 'Again Updated Date Test', '$createdAt' => '2022-08-01 13:09:23.040', // $createdAt is not updatable - '$updatedAt' => '2022-08-01 13:09:23.050' // system will update it not api - ] + '$updatedAt' => '2022-08-01 13:09:23.050', // system will update it not api + ], ]); $this->assertEquals($document['body']['title'], 'Again Updated Date Test'); @@ -3188,7 +3182,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'Empty Permissions', @@ -3198,10 +3192,10 @@ trait DatabasesBase $databaseId = $database['body']['$id']; // Create collection - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -3220,10 +3214,10 @@ trait DatabasesBase $moviesId = $movies['body']['$id']; // create attribute - $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/attributes/string', array_merge([ + $title = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'title', 'size' => 256, @@ -3236,7 +3230,7 @@ trait DatabasesBase sleep(2); // add document - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3260,20 +3254,20 @@ trait DatabasesBase $this->assertContains(Permission::delete(Role::any()), $document['body']['$permissions']); // Send only read permission - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), - ] + ], ]); $this->assertEquals(200, $document['headers']['status-code']); $this->assertCount(1, $document['body']['$permissions']); // Send only mutation permissions - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents/' . $id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3291,7 +3285,7 @@ trait DatabasesBase } // remove collection - $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $moviesId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$moviesId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3309,39 +3303,39 @@ trait DatabasesBase /** * Test for SUCCESS */ - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), - 'name' => 'Boolean' + 'name' => 'Boolean', ]); $this->assertEquals(201, $collection['headers']['status-code']); $collectionId = $collection['body']['$id']; - $true = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([ + $true = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'true', 'required' => false, - 'default' => true + 'default' => true, ]); $this->assertEquals(202, $true['headers']['status-code']); - $false = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([ + $false = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'false', 'required' => false, - 'default' => false + 'default' => false, ]); $this->assertEquals(202, $false['headers']['status-code']); @@ -3354,10 +3348,10 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $person = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => 'person', 'name' => 'person', @@ -3372,10 +3366,10 @@ trait DatabasesBase $this->assertEquals(201, $person['headers']['status-code']); - $library = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $library = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => 'library', 'name' => 'library', @@ -3389,10 +3383,10 @@ trait DatabasesBase $this->assertEquals(201, $library['headers']['status-code']); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'fullName', 'size' => 255, @@ -3401,10 +3395,10 @@ trait DatabasesBase sleep(1); // Wait for worker - $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/relationship', array_merge([ + $relation = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => 'library', 'type' => Database::RELATION_ONE_TO_ONE, @@ -3415,10 +3409,10 @@ trait DatabasesBase sleep(1); // Wait for worker - $libraryName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $library['body']['$id'] . '/attributes/string', array_merge([ + $libraryName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$library['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'libraryName', 'size' => 255, @@ -3433,10 +3427,10 @@ trait DatabasesBase $this->assertEquals('relationship', $relation['body']['type']); $this->assertEquals('processing', $relation['body']['status']); - $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes', array_merge([ + $attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $attributes['headers']['status-code']); @@ -3451,7 +3445,7 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$person['body']['$id']}/attributes/library", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $attribute['headers']['status-code']); @@ -3465,7 +3459,7 @@ trait DatabasesBase $this->assertEquals('person', $attribute['body']['twoWayKey']); $this->assertEquals(Database::RELATION_MUTATE_CASCADE, $attribute['body']['onDelete']); - $person1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + $person1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3483,13 +3477,13 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); // Create without nested ID - $person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + $person2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3503,7 +3497,7 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals('Library 2', $person2['body']['library']['libraryName']); @@ -3520,21 +3514,21 @@ trait DatabasesBase $this->assertArrayNotHasKey('$internalId', $person1['body']); $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ 'equal("library", "library1")', - 'select(["fullName","library.*"])' - ] + 'select(["fullName","library.*"])', + ], ]); $this->assertEquals(1, $documents['body']['total']); $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); $this->assertArrayHasKey('fullName', $documents['body']['documents'][0]); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3546,10 +3540,10 @@ trait DatabasesBase $this->assertEquals(400, $documents['headers']['status-code']); $this->assertEquals('Invalid query: Cannot query nested attribute on: library', $documents['body']['message']); - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/library', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes/library', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); sleep(2); @@ -3559,12 +3553,12 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$person['body']['$id']}/attributes/library", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(404, $attribute['headers']['status-code']); - $person1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/' . $person1['body']['$id'], array_merge([ + $person1 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents/'.$person1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3572,10 +3566,10 @@ trait DatabasesBase $this->assertArrayNotHasKey('library', $person1['body']); //Test Deletion of related twoKey - $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $library['body']['$id'] . '/attributes', array_merge([ + $attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$library['body']['$id'].'/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $attributes['headers']['status-code']); @@ -3599,10 +3593,10 @@ trait DatabasesBase $libraryCollection = $data['libraryCollection']; // One person can own several libraries - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $personCollection . '/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$personCollection.'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => 'library', 'type' => Database::RELATION_ONE_TO_MANY, @@ -3613,20 +3607,20 @@ trait DatabasesBase sleep(1); - $libraryAttributesResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection . '/attributes', array_merge([ + $libraryAttributesResponse = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$libraryCollection.'/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertIsArray($libraryAttributesResponse['body']['attributes']); $this->assertEquals(2, $libraryAttributesResponse['body']['total']); $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['attributes'][1]['key']); - $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection, array_merge([ + $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$libraryCollection, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertIsArray($libraryCollectionResponse['body']['attributes']); @@ -3635,7 +3629,7 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$personCollection}/attributes/libraries", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $attribute['headers']['status-code']); @@ -3649,7 +3643,7 @@ trait DatabasesBase $this->assertEquals('person_one_to_many', $attribute['body']['twoWayKey']); $this->assertEquals('restrict', $attribute['body']['onDelete']); - $person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $personCollection . '/documents', array_merge([ + $person2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$personCollection.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3674,21 +3668,21 @@ trait DatabasesBase Permission::delete(Role::any()), ], 'libraryName' => 'Library 11', - ] + ], ], ], 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), - ] + ], ]); $this->assertEquals(201, $person2['headers']['status-code']); $this->assertArrayHasKey('libraries', $person2['body']); $this->assertEquals(2, count($person2['body']['libraries'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $personCollection . '/documents/' . $person2['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$personCollection.'/documents/'.$person2['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3698,7 +3692,7 @@ trait DatabasesBase $this->assertArrayHasKey('libraries', $response['body']); $this->assertEquals(2, count($response['body']['libraries'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection . '/documents/library11', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$libraryCollection.'/documents/library11', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3707,10 +3701,10 @@ trait DatabasesBase $this->assertArrayHasKey('person_one_to_many', $response['body']); $this->assertEquals('person10', $response['body']['person_one_to_many']['$id']); - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $personCollection . '/attributes/libraries/relationship', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$personCollection.'/attributes/libraries/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'onDelete' => Database::RELATION_MUTATE_CASCADE, ]); @@ -3720,7 +3714,7 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$personCollection}/attributes/libraries", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $attribute['headers']['status-code']); @@ -3744,10 +3738,10 @@ trait DatabasesBase $databaseId = $data['databaseId']; // Create album collection - $albums = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $albums = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Albums', @@ -3759,10 +3753,10 @@ trait DatabasesBase ]); // Create album name attribute - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 255, @@ -3770,10 +3764,10 @@ trait DatabasesBase ]); // Create artist collection - $artists = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $artists = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Artists', @@ -3785,10 +3779,10 @@ trait DatabasesBase ]); // Create artist name attribute - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $artists['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$artists['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 255, @@ -3796,10 +3790,10 @@ trait DatabasesBase ]); // Create relationship - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/attributes/relationship', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $artists['body']['$id'], 'type' => Database::RELATION_MANY_TO_ONE, @@ -3826,7 +3820,7 @@ trait DatabasesBase ]; // Create album - $album = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/documents', array_merge([ + $album = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3848,7 +3842,7 @@ trait DatabasesBase $this->assertEquals($permissions, $album['body']['$permissions']); $this->assertEquals($permissions, $album['body']['artist']['$permissions']); - $album = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/documents/album1', array_merge([ + $album = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/documents/album1', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3860,7 +3854,7 @@ trait DatabasesBase $this->assertEquals($permissions, $album['body']['$permissions']); $this->assertEquals($permissions, $album['body']['artist']['$permissions']); - $artist = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $artists['body']['$id'] . '/documents/' . $album['body']['artist']['$id'], array_merge([ + $artist = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$artists['body']['$id'].'/documents/'.$album['body']['artist']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3888,10 +3882,10 @@ trait DatabasesBase $databaseId = $data['databaseId']; // Create sports collection - $sports = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $sports = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Sports', @@ -3903,10 +3897,10 @@ trait DatabasesBase ]); // Create sport name attribute - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 255, @@ -3914,10 +3908,10 @@ trait DatabasesBase ]); // Create player collection - $players = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $players = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Players', @@ -3929,10 +3923,10 @@ trait DatabasesBase ]); // Create player name attribute - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $players['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$players['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 255, @@ -3940,10 +3934,10 @@ trait DatabasesBase ]); // Create relationship - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/attributes/relationship', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $players['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, @@ -3971,7 +3965,7 @@ trait DatabasesBase ]; // Create sport - $sport = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/documents', array_merge([ + $sport = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3987,7 +3981,7 @@ trait DatabasesBase [ '$id' => 'player2', 'name' => 'Player 2', - ] + ], ], ], ]); @@ -4001,7 +3995,7 @@ trait DatabasesBase $this->assertEquals($permissions, $sport['body']['players'][0]['$permissions']); $this->assertEquals($permissions, $sport['body']['players'][1]['$permissions']); - $sport = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/documents/sport1', array_merge([ + $sport = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/documents/sport1', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -4015,7 +4009,7 @@ trait DatabasesBase $this->assertEquals($permissions, $sport['body']['players'][0]['$permissions']); $this->assertEquals($permissions, $sport['body']['players'][1]['$permissions']); - $player = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $players['body']['$id'] . '/documents/' . $sport['body']['players'][0]['$id'], array_merge([ + $player = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$players['body']['$id'].'/documents/'.$sport['body']['players'][0]['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -4040,7 +4034,7 @@ trait DatabasesBase */ public function testValidateOperators(array $data): void { - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -4058,21 +4052,21 @@ trait DatabasesBase $this->assertEquals('Stevie Wonder', $response['body']['documents'][0]['fullName']); $this->assertEquals(2, count($response['body']['documents'][0]['libraries'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ 'isNotNull("$id")', 'isNull("fullName")', - 'select(["fullName"])' + 'select(["fullName"])', ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, count($response['body']['documents'])); $this->assertEquals(null, $response['body']['documents'][0]['fullName']); - $this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]); + $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); } /** @@ -4080,20 +4074,20 @@ trait DatabasesBase */ public function testSelectsQueries(array $data): void { - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ 'equal("fullName", "Stevie Wonder")', - 'select(["fullName"])' + 'select(["fullName"])', ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -4105,12 +4099,12 @@ trait DatabasesBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents/' . $document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents/'.$document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - 'select(["fullName", "$id"])' + 'select(["fullName", "$id"])', ], ]); @@ -4121,18 +4115,20 @@ trait DatabasesBase /** * @depends testCreateDatabase - * @param array $data + * + * @param array $data * @return void + * * @throws \Exception */ public function testUpdateWithExistingRelationships(array $data): void { $databaseId = $data['databaseId']; - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Collection1', @@ -4143,10 +4139,10 @@ trait DatabasesBase ], ]); - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Collection2', @@ -4160,42 +4156,42 @@ trait DatabasesBase $collection1 = $collection1['body']['$id']; $collection2 = $collection2['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => '49', 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2 . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection2.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => '49', 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1.'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $collection2, 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, - 'key' => 'collection2' + 'key' => 'collection2', ]); sleep(1); - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1.'/documents', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ @@ -4208,9 +4204,9 @@ trait DatabasesBase ], ]); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1 . '/documents/' . $document['body']['$id'], array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1.'/documents/'.$document['body']['$id'], array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ 'name' => 'Document 1 Updated', diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php index 17059adf88..947b0ed7fe 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php @@ -2,9 +2,9 @@ namespace Tests\E2E\Services\Databases; -use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -32,7 +32,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -53,7 +53,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still create collections */ - $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, array_merge([ + $database = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -63,7 +63,7 @@ class DatabasesConsoleClientTest extends Scope $this->assertFalse($database['body']['enabled']); - $tvShows = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $tvShows = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -86,7 +86,8 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * @param array $data + * + * @param array $data */ public function testListCollection(array $data) { @@ -95,10 +96,10 @@ class DatabasesConsoleClientTest extends Scope */ $databaseId = $data['databaseId']; - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); $this->assertEquals(200, $collections['headers']['status-code']); @@ -107,7 +108,8 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * @param array $data + * + * @param array $data */ public function testGetCollection(array $data) { @@ -117,7 +119,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still call get collection */ - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $moviesCollectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$moviesCollectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -130,7 +132,8 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * @param array $data + * + * @param array $data */ public function testUpdateCollection(array $data) { @@ -140,12 +143,12 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still call update collection */ - $collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $moviesCollectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$moviesCollectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Movies Updated', - 'enabled' => false + 'enabled' => false, ]); $this->assertEquals(200, $collection['headers']['status-code']); @@ -156,7 +159,8 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * @param array $data + * + * @param array $data */ public function testDeleteCollection(array $data) { @@ -166,13 +170,13 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still call Delete collection */ - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $tvShowsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$tvShowsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals($response['body'], ""); + $this->assertEquals($response['body'], ''); } /** @@ -184,12 +188,11 @@ class DatabasesConsoleClientTest extends Scope /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '32h' + 'range' => '32h', ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -197,12 +200,11 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -212,7 +214,6 @@ class DatabasesConsoleClientTest extends Scope $this->assertIsArray($response['body']['collectionsTotal']); } - /** * @depends testCreateCollection */ @@ -222,21 +223,20 @@ class DatabasesConsoleClientTest extends Scope /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '32h' + 'range' => '32h', ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/randomCollectionId/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/randomCollectionId/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -244,11 +244,11 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(count($response['body']), 2); @@ -265,7 +265,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -274,11 +274,11 @@ class DatabasesConsoleClientTest extends Scope $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 1 + 'limit' => 1, ]); $this->assertEquals(200, $logs['headers']['status-code']); @@ -286,23 +286,23 @@ class DatabasesConsoleClientTest extends Scope $this->assertLessThanOrEqual(1, count($logs['body']['logs'])); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'offset' => 1 + 'offset' => 1, ]); $this->assertEquals(200, $logs['headers']['status-code']); $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'offset' => 1, - 'limit' => 1 + 'limit' => 1, ]); $this->assertEquals(200, $logs['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index 743df9e53a..b5abaebfad 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -21,23 +21,22 @@ class DatabasesCustomClientTest extends Scope /** * Test for SUCCESS */ - $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'databaseId' => ID::unique(), - 'name' => 'Test Database' + 'name' => 'Test Database', ]); $databaseId = $database['body']['$id']; // Collection aliases write to create, update, delete - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -53,10 +52,10 @@ class DatabasesCustomClientTest extends Scope $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/attributes/string', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'title', 'size' => 256, @@ -68,7 +67,7 @@ class DatabasesCustomClientTest extends Scope $this->assertEquals(202, $response['headers']['status-code']); // Document aliases write to update, delete - $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -78,7 +77,7 @@ class DatabasesCustomClientTest extends Scope ], 'permissions' => [ Permission::write(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertNotContains(Permission::create(Role::user($this->getUser()['$id'])), $document1['body']['$permissions']); @@ -90,7 +89,7 @@ class DatabasesCustomClientTest extends Scope */ // Document does not allow create permission - $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -100,7 +99,7 @@ class DatabasesCustomClientTest extends Scope ], 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals(400, $document2['headers']['status-code']); @@ -114,7 +113,7 @@ class DatabasesCustomClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); @@ -123,7 +122,7 @@ class DatabasesCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::custom('permissionCheckDatabase'), 'name' => 'Test Database', @@ -133,10 +132,10 @@ class DatabasesCustomClientTest extends Scope $databaseId = $database['body']['$id']; // Create collection - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('permissionCheck'), 'name' => 'permissionCheck', @@ -146,10 +145,10 @@ class DatabasesCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); // Add attribute to collection - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/permissionCheck/attributes/string', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/permissionCheck/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 255, @@ -161,10 +160,10 @@ class DatabasesCustomClientTest extends Scope sleep(2); // Creating document by server, give read permission to our user + some other user - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/permissionCheck/documents', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/permissionCheck/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'documentId' => ID::custom('permissionCheckDocument'), 'data' => [ @@ -182,44 +181,43 @@ class DatabasesCustomClientTest extends Scope // Update document // This is the point of this test. We should be allowed to do this action, and it should not fail on permission check - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ 'name' => 'AppwriteExpert', - ] + ], ]); $this->assertEquals(200, $response['headers']['status-code']); // Get name of the document, should be the new one - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals("AppwriteExpert", $response['body']['name']); + $this->assertEquals('AppwriteExpert', $response['body']['name']); // Cleanup to prevent collision with other tests // Delete collection - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/permissionCheck', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/permissionCheck', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $response['headers']['status-code']); - // Wait for database worker to finish deleting collection sleep(2); // Make sure collection has been deleted - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/permissionCheck', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/permissionCheck', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(404, $response['headers']['status-code']); @@ -228,24 +226,22 @@ class DatabasesCustomClientTest extends Scope public function testUpdateTwoWayRelationship(): void { - $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'databaseId' => ID::unique(), - 'name' => 'Test Database' + 'name' => 'Test Database', ]); $databaseId = $database['body']['$id']; - // Creating collection 1 - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'level1', @@ -255,14 +251,14 @@ class DatabasesCustomClientTest extends Scope Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); // Creating collection 2 - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'level2', @@ -272,41 +268,41 @@ class DatabasesCustomClientTest extends Scope Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); \sleep(2); // Creating two way relationship between collection 1 and collection 2 from collection 1 - $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([ + $relation = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $collection2['body']['$id'], 'type' => 'oneToMany', 'twoWay' => true, 'onDelete' => 'cascade', 'key' => $collection2['body']['$id'], - 'twoWayKey' => $collection1['body']['$id'] + 'twoWayKey' => $collection1['body']['$id'], ]); \sleep(3); // Update relation from collection 2 to on delete restrict - $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/' . $collection1['body']['$id'] . '/relationship', array_merge([ + $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/attributes/'.$collection1['body']['$id'].'/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'onDelete' => 'restrict', ]); // Fetching attributes after updating relation to compare - $collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'], [ + $collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]); $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; @@ -323,7 +319,7 @@ class DatabasesCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'databaseId' => ID::unique(), 'name' => ID::unique(), @@ -332,10 +328,10 @@ class DatabasesCustomClientTest extends Scope $databaseId = $database['body']['$id']; // Creating collection 1 - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection1'), 'name' => ID::custom('collection1'), @@ -344,27 +340,27 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ] + ], ]); // Creating collection 2 - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), 'documentSecurity' => false, 'permissions' => [ Permission::read(Role::user($userId)), - ] + ], ]); - $collection3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), @@ -373,26 +369,26 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ] + ], ]); - $collection4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection4 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection4'), 'name' => ID::custom('collection4'), 'documentSecurity' => false, 'permissions' => [ Permission::read(Role::user($userId)), - ] + ], ]); - $collection5 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection5 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection5'), 'name' => ID::custom('collection5'), @@ -401,115 +397,115 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ] + ], ]); // Creating one to one relationship from collection 1 to colletion 2 - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $collection2['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection2['body']['$id'] + 'key' => $collection2['body']['$id'], ]); // Creating one to one relationship from collection 2 to colletion 3 - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $collection3['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection3['body']['$id'] + 'key' => $collection3['body']['$id'], ]); // Creating one to one relationship from collection 3 to colletion 4 - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection3['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $collection4['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection4['body']['$id'] + 'key' => $collection4['body']['$id'], ]); // Creating one to one relationship from collection 4 to colletion 5 - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection4['body']['$id'] . '/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection4['body']['$id'].'/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'relatedCollectionId' => $collection5['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection5['body']['$id'] + 'key' => $collection5['body']['$id'], ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'key' => "Title", + 'key' => 'Title', 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'key' => "Rating", + 'key' => 'Rating', 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection3['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'key' => "Rating", + 'key' => 'Rating', 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection4['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection4['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'key' => "Rating", + 'key' => 'Rating', 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection5['body']['$id'] . '/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection5['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'key' => "Rating", + 'key' => 'Rating', 'size' => 100, 'required' => false, 'array' => false, @@ -518,10 +514,10 @@ class DatabasesCustomClientTest extends Scope \sleep(2); // Creating parent document with a child reference to test the permissions - $parentDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents', array_merge([ + $parentDocument = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'documentId' => ID::custom($collection1['body']['$id']), 'data' => [ @@ -537,17 +533,17 @@ class DatabasesCustomClientTest extends Scope 'Rating' => '10', $collection5['body']['$id'] => [ '$id' => ID::custom($collection5['body']['$id']), - 'Rating' => '10' - ] - ] - ] - ] - ] + 'Rating' => '10', + ], + ], + ], + ], + ], ]); $this->assertEquals(201, $parentDocument['headers']['status-code']); // This is the point of the test. We should not need any authorization permission to update the document with same data. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -565,21 +561,21 @@ class DatabasesCustomClientTest extends Scope 'Rating' => '10', $collection5['body']['$id'] => [ '$id' => $collection5['body']['$id'], - 'Rating' => '10' - ] - ] - ] - ] - ] + 'Rating' => '10', + ], + ], + ], + ], + ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($parentDocument['body'], $response['body']); // Giving update permission of collection 3 to user. - $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection3', array_merge([ + $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/collection3', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), @@ -589,11 +585,11 @@ class DatabasesCustomClientTest extends Scope Permission::read(Role::user($userId)), Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), - ] + ], ]); // This is the point of this test. We should be allowed to do this action, and it should not fail on permission check - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -610,19 +606,19 @@ class DatabasesCustomClientTest extends Scope 'Rating' => '10', $collection5['body']['$id'] => [ '$id' => ID::custom($collection5['body']['$id']), - 'Rating' => '11' - ] - ] - ] - ] - ] + 'Rating' => '11', + ], + ], + ], + ], + ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(11, $response['body'][$collection2['body']['$id']]['collection3']['Rating']); // We should not be allowed to update the document as we do not have permission for collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -632,29 +628,29 @@ class DatabasesCustomClientTest extends Scope '$id' => ID::custom($collection2['body']['$id']), 'Rating' => '11', $collection3['body']['$id'] => null, - ] - ] + ], + ], ]); $this->assertEquals(401, $response['headers']['status-code']); // We should not be allowed to update the document as we do not have permission for collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/documents/' . $collection2['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/documents/'.$collection2['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ 'Rating' => '11', - ] + ], ]); $this->assertEquals(401, $response['headers']['status-code']); // Removing update permission from collection 3. - $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection3', array_merge([ + $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/collection3', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), @@ -663,14 +659,14 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ] + ], ]); // Giving update permission to collection 2. - $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection2', array_merge([ + $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/collection2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), @@ -680,25 +676,25 @@ class DatabasesCustomClientTest extends Scope Permission::update(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ] + ], ]); // Creating collection 3 new document - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/documents', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection3['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'documentId' => ID::custom('collection3Doc1'), 'data' => [ - 'Rating' => '20' - ] + 'Rating' => '20', + ], ]); $this->assertEquals(201, $response['headers']['status-code']); // We should be allowed to link a new document from collection 3 to collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -707,15 +703,14 @@ class DatabasesCustomClientTest extends Scope $collection2['body']['$id'] => [ '$id' => ID::custom($collection2['body']['$id']), $collection3['body']['$id'] => 'collection3Doc1', - ] - ] + ], + ], ]); $this->assertEquals(200, $response['headers']['status-code']); - // We should be allowed to link and create a new document from collection 3 to collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -724,10 +719,10 @@ class DatabasesCustomClientTest extends Scope $collection2['body']['$id'] => [ '$id' => ID::custom($collection2['body']['$id']), $collection3['body']['$id'] => [ - '$id' => ID::custom('collection3Doc2') + '$id' => ID::custom('collection3Doc2'), ], - ] - ] + ], + ], ]); $this->assertEquals(200, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 648a4de800..57b609c33a 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -3,10 +3,10 @@ namespace Tests\E2E\Services\Databases; use Appwrite\Extend\Exception as AppwriteException; +use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use Tests\E2E\Client; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -22,7 +22,7 @@ class DatabasesCustomServerTest extends Scope $test1 = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::custom('first'), 'name' => 'Test 1', @@ -34,7 +34,7 @@ class DatabasesCustomServerTest extends Scope $test2 = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::custom('second'), 'name' => 'Test 2', @@ -124,7 +124,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['databases'][0]['$id'] . '")'], + 'queries' => ['cursorAfter("'.$base['body']['databases'][0]['$id'].'")'], ]); $this->assertCount(1, $databases['body']['databases']); @@ -134,7 +134,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['databases'][1]['$id'] . '")'], + 'queries' => ['cursorAfter("'.$base['body']['databases'][1]['$id'].'")'], ]); $this->assertCount(0, $databases['body']['databases']); @@ -152,7 +152,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['databases'][1]['$id'] . '")'], + 'queries' => ['cursorBefore("'.$base['body']['databases'][1]['$id'].'")'], ]); $this->assertCount(1, $databases['body']['databases']); @@ -162,7 +162,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['databases'][0]['$id'] . '")'], + 'queries' => ['cursorBefore("'.$base['body']['databases'][0]['$id'].'")'], ]); $this->assertCount(0, $databases['body']['databases']); @@ -175,7 +175,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'first' + 'search' => 'first', ]); $this->assertEquals(1, $databases['body']['total']); @@ -185,7 +185,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Test' + 'search' => 'Test', ]); $this->assertEquals(2, $databases['body']['total']); @@ -196,7 +196,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Nonexistent' + 'search' => 'Nonexistent', ]); $this->assertEquals(0, $databases['body']['total']); @@ -217,13 +217,14 @@ class DatabasesCustomServerTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test 1', 'databaseId' => ID::custom('first'), ]); $this->assertEquals(409, $response['headers']['status-code']); + return ['databaseId' => $test1['body']['$id']]; } @@ -236,16 +237,17 @@ class DatabasesCustomServerTest extends Scope /** * Test for SUCCESS */ - $database = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, [ + $database = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]); $this->assertEquals(200, $database['headers']['status-code']); $this->assertEquals($databaseId, $database['body']['$id']); $this->assertEquals('Test 1', $database['body']['name']); $this->assertEquals(true, $database['body']['enabled']); + return ['databaseId' => $database['body']['$id']]; } @@ -256,10 +258,10 @@ class DatabasesCustomServerTest extends Scope { $databaseId = $data['databaseId']; - $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, [ + $database = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'name' => 'Test 1 Updated', 'enabled' => false, @@ -270,12 +272,12 @@ class DatabasesCustomServerTest extends Scope $this->assertFalse($database['body']['enabled']); // Now update the database without the passing the enabled parameter - $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, [ + $database = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'name' => 'Test 1' + 'name' => 'Test 1', ]); $this->assertEquals(200, $database['headers']['status-code']); @@ -290,19 +292,19 @@ class DatabasesCustomServerTest extends Scope { $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals("", $response['body']); + $this->assertEquals('', $response['body']); // Try to get the collection and check if it has been deleted - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); @@ -313,7 +315,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -326,10 +328,10 @@ class DatabasesCustomServerTest extends Scope /** * Test for SUCCESS */ - $test1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $test1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test 1', 'collectionId' => ID::custom('first'), @@ -342,10 +344,10 @@ class DatabasesCustomServerTest extends Scope 'documentSecurity' => true, ]); - $test2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $test2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test 2', 'collectionId' => ID::custom('second'), @@ -358,7 +360,7 @@ class DatabasesCustomServerTest extends Scope 'documentSecurity' => true, ]); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -371,41 +373,41 @@ class DatabasesCustomServerTest extends Scope $base = array_reverse($collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'] + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $collections['headers']['status-code']); $this->assertCount(1, $collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'] + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $collections['headers']['status-code']); $this->assertCount(1, $collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("enabled", true)'] + 'queries' => ['equal("enabled", true)'], ]); $this->assertEquals(200, $collections['headers']['status-code']); $this->assertCount(2, $collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("enabled", false)'] + 'queries' => ['equal("enabled", false)'], ]); $this->assertEquals(200, $collections['headers']['status-code']); @@ -414,7 +416,7 @@ class DatabasesCustomServerTest extends Scope /** * Test for Order */ - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -428,26 +430,26 @@ class DatabasesCustomServerTest extends Scope /** * Test for After */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['collections'][0]['$id'] . '")'], + 'queries' => ['cursorAfter("'.$base['body']['collections'][0]['$id'].'")'], ]); $this->assertCount(1, $collections['body']['collections']); $this->assertEquals($base['body']['collections'][1]['$id'], $collections['body']['collections'][0]['$id']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $base['body']['collections'][1]['$id'] . '")'], + 'queries' => ['cursorAfter("'.$base['body']['collections'][1]['$id'].'")'], ]); $this->assertCount(0, $collections['body']['collections']); @@ -456,26 +458,26 @@ class DatabasesCustomServerTest extends Scope /** * Test for Before */ - $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['collections'][1]['$id'] . '")'], + 'queries' => ['cursorBefore("'.$base['body']['collections'][1]['$id'].'")'], ]); $this->assertCount(1, $collections['body']['collections']); $this->assertEquals($base['body']['collections'][0]['$id'], $collections['body']['collections'][0]['$id']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("' . $base['body']['collections'][0]['$id'] . '")'], + 'queries' => ['cursorBefore("'.$base['body']['collections'][0]['$id'].'")'], ]); $this->assertCount(0, $collections['body']['collections']); @@ -484,32 +486,32 @@ class DatabasesCustomServerTest extends Scope /** * Test for Search */ - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'first' + 'search' => 'first', ]); $this->assertEquals(1, $collections['body']['total']); $this->assertEquals('first', $collections['body']['collections'][0]['$id']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Test' + 'search' => 'Test', ]); $this->assertEquals(2, $collections['body']['total']); $this->assertEquals('Test 1', $collections['body']['collections'][0]['name']); $this->assertEquals('Test 2', $collections['body']['collections'][1]['name']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Nonexistent' + 'search' => 'Nonexistent', ]); $this->assertEquals(0, $collections['body']['total']); @@ -517,7 +519,7 @@ class DatabasesCustomServerTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -527,10 +529,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); // This collection already exists - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test 1', 'collectionId' => ID::custom('first'), @@ -544,6 +546,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(409, $response['headers']['status-code']); + return [ 'databaseId' => $databaseId, 'collectionId' => $test1['body']['$id'], @@ -558,10 +561,10 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); $this->assertEquals(200, $collection['headers']['status-code']); @@ -578,13 +581,13 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test 1 Updated', - 'enabled' => false + 'enabled' => false, ]); $this->assertEquals(200, $collection['headers']['status-code']); @@ -594,11 +597,10 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testListCollections + * @depends testListCollections */ public function testCreateEncryptedAttribute(array $data): void { - $databaseId = $data['databaseId']; /** @@ -606,10 +608,10 @@ class DatabasesCustomServerTest extends Scope */ // Create collection - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Encrypted Actors Data', @@ -628,23 +630,22 @@ class DatabasesCustomServerTest extends Scope /** * Test for creating encrypted attributes */ + $attributesPath = '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes'; - $attributesPath = '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes'; - - $firstName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ + $firstName = $this->client->call(Client::METHOD_POST, $attributesPath.'/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'firstName', 'size' => 256, 'required' => true, ]); - $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ + $lastName = $this->client->call(Client::METHOD_POST, $attributesPath.'/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'lastName', 'size' => 256, @@ -652,7 +653,6 @@ class DatabasesCustomServerTest extends Scope 'encrypt' => true, ]); - /** * Check status of every attribute */ @@ -668,10 +668,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Creating document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'documentId' => ID::unique(), 'data' => [ @@ -686,10 +686,10 @@ class DatabasesCustomServerTest extends Scope ]); // Check document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents/' . $document['body']['$id'], array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents/'.$document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $document['headers']['status-code']); @@ -702,7 +702,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -716,10 +716,10 @@ class DatabasesCustomServerTest extends Scope */ // Create collection - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -735,30 +735,30 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $actors['headers']['status-code']); $this->assertEquals($actors['body']['name'], 'Actors'); - $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([ + $firstName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'firstName', 'size' => 256, 'required' => true, ]); - $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([ + $lastName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'lastName', 'size' => 256, 'required' => true, ]); - $unneeded = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([ + $unneeded = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'unneeded', 'size' => 256, @@ -769,16 +769,16 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Creating document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'lorem', 'lastName' => 'ipsum', - 'unneeded' => 'dolor' + 'unneeded' => 'dolor', ], 'permissions' => [ Permission::read(Role::any()), @@ -787,10 +787,10 @@ class DatabasesCustomServerTest extends Scope ], ]); - $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'key_lastName', 'type' => 'key', @@ -802,10 +802,10 @@ class DatabasesCustomServerTest extends Scope // Wait for database worker to finish creating index sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); $unneededId = $unneeded['body']['key']; @@ -820,10 +820,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($collection['body']['indexes'][0]['key'], $index['body']['key']); // Delete attribute - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actors ['body']['$id'] . '/attributes/' . $unneededId, array_merge([ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/'.$unneededId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $attribute['headers']['status-code']); @@ -831,18 +831,18 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Check document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents/' . $document['body']['$id'], array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents/'.$document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertNotContains($unneededId, $document['body']); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); $this->assertEquals(200, $collection['headers']['status-code']); @@ -854,7 +854,7 @@ class DatabasesCustomServerTest extends Scope return [ 'collectionId' => $actors['body']['$id'], 'key' => $index['body']['key'], - 'databaseId' => $databaseId + 'databaseId' => $databaseId, ]; } @@ -864,10 +864,10 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndex($data): array { $databaseId = $data['databaseId']; - $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes/' . $data['key'], array_merge([ + $index = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/indexes/'.$data['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $index['headers']['status-code']); @@ -875,10 +875,10 @@ class DatabasesCustomServerTest extends Scope // Wait for database worker to finish deleting index sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['collectionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); $this->assertCount(0, $collection['body']['indexes']); @@ -892,20 +892,20 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndexOnDeleteAttribute($data) { $databaseId = $data['databaseId']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'attribute1', 'size' => 16, 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'attribute2', 'size' => 16, @@ -919,10 +919,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); - $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ + $index1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'index1', 'type' => 'key', @@ -930,10 +930,10 @@ class DatabasesCustomServerTest extends Scope 'orders' => ['ASC', 'ASC'], ]); - $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ + $index2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'index2', 'type' => 'key', @@ -948,10 +948,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/'.$attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -959,10 +959,10 @@ class DatabasesCustomServerTest extends Scope // wait for database worker to complete sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['collectionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -974,10 +974,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/'.$attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -990,7 +990,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -999,10 +999,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'TestCleanupDuplicateIndexOnDeleteAttribute', @@ -1020,20 +1020,20 @@ class DatabasesCustomServerTest extends Scope $collectionId = $collection['body']['$id']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'attribute1', 'size' => 16, 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'attribute2', 'size' => 16, @@ -1047,10 +1047,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); - $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + $index1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'index1', 'type' => 'key', @@ -1058,10 +1058,10 @@ class DatabasesCustomServerTest extends Scope 'orders' => ['ASC', 'ASC'], ]); - $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + $index2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'index2', 'type' => 'key', @@ -1076,10 +1076,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -1087,10 +1087,10 @@ class DatabasesCustomServerTest extends Scope // wait for database worker to complete sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -1102,10 +1102,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($attribute2['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -1120,7 +1120,7 @@ class DatabasesCustomServerTest extends Scope $collectionId = $data['collectionId']; // Add Documents to the collection - $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1136,7 +1136,7 @@ class DatabasesCustomServerTest extends Scope ], ]); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1165,19 +1165,19 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($document2['body']['lastName'], 'Jackson'); // Delete the actors collection - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals($response['body'], ""); + $this->assertEquals($response['body'], ''); // Try to get the collection and check if it has been deleted - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); @@ -1242,7 +1242,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -1251,10 +1251,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('attributeRowWidthLimit'), 'name' => 'attributeRowWidthLimit', @@ -1274,10 +1274,10 @@ class DatabasesCustomServerTest extends Scope // Add wide string attributes to approach row width limit for ($i = 0; $i < 15; $i++) { - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => "attribute{$i}", 'size' => 1024, @@ -1289,10 +1289,10 @@ class DatabasesCustomServerTest extends Scope sleep(5); - $tooWide = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $tooWide = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'tooWide', 'size' => 1024, @@ -1308,7 +1308,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -1317,10 +1317,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('testLimitException'), 'name' => 'testLimitException', @@ -1341,10 +1341,10 @@ class DatabasesCustomServerTest extends Scope // add unique attributes for indexing for ($i = 0; $i < 64; $i++) { // $this->assertEquals(true, static::getDatabase()->createAttribute('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => "attribute{$i}", 'size' => 64, @@ -1356,10 +1356,10 @@ class DatabasesCustomServerTest extends Scope sleep(10); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -1370,7 +1370,7 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(0, $collection['body']['indexes']); foreach ($collection['body']['attributes'] as $attribute) { - $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); + $this->assertEquals('available', $attribute['status'], 'attribute: '.$attribute['key']); } // Test indexLimit = 64 @@ -1378,10 +1378,10 @@ class DatabasesCustomServerTest extends Scope // Add up to the limit, then check if the next index throws IndexLimitException for ($i = 0; $i < 59; $i++) { // $this->assertEquals(true, static::getDatabase()->createIndex('indexLimit', "index{$i}", Database::INDEX_KEY, ["test{$i}"], [16])); - $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => "key_attribute{$i}", 'type' => 'key', @@ -1394,10 +1394,10 @@ class DatabasesCustomServerTest extends Scope sleep(5); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -1407,10 +1407,10 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(64, $collection['body']['attributes']); $this->assertCount(59, $collection['body']['indexes']); - $tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + $tooMany = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'tooMany', 'type' => 'key', @@ -1420,10 +1420,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $tooMany['headers']['status-code']); $this->assertEquals('Index limit exceeded', $tooMany['body']['message']); - $collection = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $collection['headers']['status-code']); @@ -1434,7 +1434,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'updateAttributes', @@ -1442,13 +1442,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $database['headers']['status-code']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::custom('updateAttributes'), - 'name' => 'updateAttributes' + 'name' => 'updateAttributes', ]); $this->assertEquals(201, $collection['headers']['status-code']); @@ -1458,14 +1458,14 @@ class DatabasesCustomServerTest extends Scope /** * Create String Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'string', 'size' => 1024, - 'required' => false + 'required' => false, ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1473,13 +1473,13 @@ class DatabasesCustomServerTest extends Scope /** * Create Email Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'email', - 'required' => false + 'required' => false, ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1487,13 +1487,13 @@ class DatabasesCustomServerTest extends Scope /** * Create IP Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'ip', - 'required' => false + 'required' => false, ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1501,13 +1501,13 @@ class DatabasesCustomServerTest extends Scope /** * Create URL Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'url', - 'required' => false + 'required' => false, ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1515,13 +1515,13 @@ class DatabasesCustomServerTest extends Scope /** * Create Integer Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'integer', - 'required' => false + 'required' => false, ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1529,50 +1529,50 @@ class DatabasesCustomServerTest extends Scope /** * Create Float Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'float', - 'required' => false + 'required' => false, ]); /** * Create Boolean Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'boolean', - 'required' => false + 'required' => false, ]); /** * Create Datetime Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'datetime', - 'required' => false + 'required' => false, ]); /** * Create Enum Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'enum', 'required' => false, - 'elements' => ['lorem', 'ipsum'] + 'elements' => ['lorem', 'ipsum'], ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1581,11 +1581,10 @@ class DatabasesCustomServerTest extends Scope return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId + 'collectionId' => $collectionId, ]; } - /** * @depends testAttributeUpdate */ @@ -1595,72 +1594,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'lorem' + 'default' => 'lorem', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertEquals('lorem', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'ipsum' + 'default' => 'ipsum', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -1669,34 +1668,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'i am no boolean', - 'default' => 'dolor' + 'default' => 'dolor', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 123 + 'default' => 123, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, ]); @@ -1704,24 +1703,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'default' => 'ipsum' + 'default' => 'ipsum', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, - 'default' => 'ipsum' + 'default' => 'ipsum', ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -1737,73 +1736,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'torsten@appwrite.io' + 'default' => 'torsten@appwrite.io', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertEquals('torsten@appwrite.io', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('torsten@appwrite.io', $attribute['default']); - - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'eldad@appwrite.io' + 'default' => 'eldad@appwrite.io', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -1812,34 +1810,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', - 'default' => 'torsten@appwrite.io' + 'default' => 'torsten@appwrite.io', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'i am no email' + 'default' => 'i am no email', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, ]); @@ -1847,24 +1845,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'default' => 'ipsum' + 'default' => 'ipsum', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, - 'default' => 'torsten@appwrite.io' + 'default' => 'torsten@appwrite.io', ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -1880,72 +1878,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => '127.0.0.1' + 'default' => '127.0.0.1', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertEquals('127.0.0.1', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('127.0.0.1', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => '192.168.0.1' + 'default' => '192.168.0.1', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -1954,34 +1952,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', - 'default' => '127.0.0.1' + 'default' => '127.0.0.1', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'i am no ip' + 'default' => 'i am no ip', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, ]); @@ -1989,24 +1987,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'default' => '127.0.0.1' + 'default' => '127.0.0.1', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, - 'default' => '127.0.0.1' + 'default' => '127.0.0.1', ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2022,72 +2020,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'http://appwrite.io' + 'default' => 'http://appwrite.io', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertEquals('http://appwrite.io', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('http://appwrite.io', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'https://appwrite.io' + 'default' => 'https://appwrite.io', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2096,34 +2094,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', - 'default' => 'https://appwrite.io' + 'default' => 'https://appwrite.io', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'i am no url' + 'default' => 'i am no url', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, ]); @@ -2131,24 +2129,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'default' => 'https://appwrite.io' + 'default' => 'https://appwrite.io', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, - 'default' => 'https://appwrite.io' + 'default' => 'https://appwrite.io', ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2164,23 +2162,23 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123, 'min' => 0, - 'max' => 1000 + 'max' => 1000, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2188,36 +2186,36 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123, $attribute['default']); $this->assertEquals(0, $attribute['min']); $this->assertEquals(1000, $attribute['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => null, 'min' => 0, - 'max' => 1000 + 'max' => 1000, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2225,23 +2223,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 456, 'min' => 100, - 'max' => 2000 + 'max' => 2000, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2252,66 +2250,66 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', 'default' => 123, 'min' => 0, - 'max' => 500 + 'max' => 500, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 'i am no integer', 'min' => 0, - 'max' => 500 + 'max' => 500, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 100, 'min' => 'i am no integer', - 'max' => 500 + 'max' => 500, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 100, 'min' => 0, - 'max' => 'i am no integer' + 'max' => 'i am no integer', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 100, @@ -2321,10 +2319,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 100, @@ -2334,10 +2332,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'min' => 0, @@ -2347,10 +2345,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'default' => 50, 'min' => 0, @@ -2360,58 +2358,57 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, 'default' => 50, 'min' => 0, - 'max' => 100 + 'max' => 100, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 50, 'min' => 55, - 'max' => 100 + 'max' => 100, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 105, 'min' => 50, - 'max' => 100 + 'max' => 100, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 50, 'min' => 200, - 'max' => 100 + 'max' => 100, ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2427,23 +2424,23 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, 'min' => 0.0, - 'max' => 1000.0 + 'max' => 1000.0, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2451,36 +2448,36 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123.456, $attribute['default']); $this->assertEquals(0, $attribute['min']); $this->assertEquals(1000, $attribute['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => null, 'min' => 0.0, - 'max' => 1000.0 + 'max' => 1000.0, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2488,23 +2485,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 456.789, 'min' => 123.456, - 'max' => 2000.0 + 'max' => 2000.0, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2515,66 +2512,66 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', 'default' => 123.456, 'min' => 0.0, - 'max' => 1000.0 + 'max' => 1000.0, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 'i am no integer', 'min' => 0.0, - 'max' => 500.0 + 'max' => 500.0, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, 'min' => 'i am no integer', - 'max' => 500.0 + 'max' => 500.0, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, 'min' => 0.0, - 'max' => 'i am no integer' + 'max' => 'i am no integer', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, @@ -2584,10 +2581,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, @@ -2597,10 +2594,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'min' => 0.0, @@ -2610,10 +2607,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'default' => 123.456, 'min' => 0.0, @@ -2623,58 +2620,57 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, 'default' => 123.456, 'min' => 0.0, - 'max' => 100.0 + 'max' => 100.0, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, 'min' => 200.0, - 'max' => 300.0 + 'max' => 300.0, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123.456, 'min' => 0.0, - 'max' => 100.0 + 'max' => 100.0, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 50.0, 'min' => 200.0, - 'max' => 100.0 + 'max' => 100.0, ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2690,72 +2686,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => true + 'default' => true, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertEquals(true, $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(true, $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => false + 'default' => false, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2764,34 +2760,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', - 'default' => true + 'default' => true, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'i am no boolean' + 'default' => 'i am no boolean', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, ]); @@ -2799,24 +2795,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'default' => false + 'default' => false, ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, - 'default' => true + 'default' => true, ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2832,72 +2828,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => '1975-06-12 14:12:55+02:00' + 'default' => '1975-06-12 14:12:55+02:00', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertEquals('1975-06-12 14:12:55+02:00', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('1975-06-12 14:12:55+02:00', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => '1965-06-12 14:12:55+02:00' + 'default' => '1965-06-12 14:12:55+02:00', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2906,34 +2902,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', - 'default' => '1975-06-12 14:12:55+02:00' + 'default' => '1975-06-12 14:12:55+02:00', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, - 'default' => 'i am no datetime' + 'default' => 'i am no datetime', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, ]); @@ -2941,24 +2937,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'default' => '1975-06-12 14:12:55+02:00' + 'default' => '1975-06-12 14:12:55+02:00', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, - 'default' => '1975-06-12 14:12:55+02:00' + 'default' => '1975-06-12 14:12:55+02:00', ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2974,22 +2970,22 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'elements' => ['lorem', 'ipsum', 'dolor'], 'required' => false, - 'default' => 'lorem' + 'default' => 'lorem', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -2999,13 +2995,13 @@ class DatabasesCustomServerTest extends Scope $this->assertContains('ipsum', $new['body']['elements']); $this->assertContains('dolor', $new['body']['elements']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); @@ -3014,22 +3010,22 @@ class DatabasesCustomServerTest extends Scope $this->assertContains('ipsum', $attribute['elements']); $this->assertContains('dolor', $attribute['elements']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'elements' => ['lorem', 'ipsum', 'dolor'], 'required' => false, - 'default' => null + 'default' => null, ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -3039,22 +3035,22 @@ class DatabasesCustomServerTest extends Scope $this->assertContains('ipsum', $new['body']['elements']); $this->assertContains('dolor', $new['body']['elements']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'elements' => ['ipsum', 'dolor'], 'required' => false, - 'default' => 'dolor' + 'default' => 'dolor', ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertFalse($new['body']['required']); @@ -3066,36 +3062,36 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'elements' => [], 'required' => false, - 'default' => 'lorem' + 'default' => 'lorem', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'elements' => ['ipsum', 'dolor'], 'required' => false, - 'default' => 'lorem' + 'default' => 'lorem', ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => 'no boolean', 'default' => 'lorem', @@ -3105,10 +3101,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 123, @@ -3118,10 +3114,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 'lorem', @@ -3131,10 +3127,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => false, 'default' => 'lorem', @@ -3143,10 +3139,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, 'elements' => ['lorem', 'ipsum', 'dolor'], @@ -3155,10 +3151,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'default' => 'lorem', 'elements' => ['lorem', 'ipsum', 'dolor'], @@ -3167,10 +3163,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'required' => true, 'default' => 'lorem', @@ -3192,51 +3188,51 @@ class DatabasesCustomServerTest extends Scope $attributes = [ 'string' => [ 'required' => false, - 'default' => 'ipsum' + 'default' => 'ipsum', ], 'email' => [ 'required' => false, - 'default' => 'eldad@appwrite.io' + 'default' => 'eldad@appwrite.io', ], 'ip' => [ 'required' => false, - 'default' => '127.0.0.1' + 'default' => '127.0.0.1', ], 'url' => [ 'required' => false, - 'default' => 'https://appwrite.io' + 'default' => 'https://appwrite.io', ], 'integer' => [ 'required' => false, 'default' => 5, 'min' => 0, - 'max' => 10 + 'max' => 10, ], 'float' => [ 'required' => false, 'default' => 5.5, 'min' => 0.0, - 'max' => 10.0 + 'max' => 10.0, ], 'datetime' => [ 'required' => false, - 'default' => '1975-06-12 14:12:55+02:00' + 'default' => '1975-06-12 14:12:55+02:00', ], 'enum' => [ 'elements' => ['lorem', 'ipsum', 'dolor'], 'required' => false, - 'default' => 'lorem' - ] + 'default' => 'lorem', + ], ]; foreach ($attributes as $key => $payload) { /** * Check if Database exists */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/i_dont_exist/collections/' . $collectionId . '/attributes/' . $key . '/unknown_' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/i_dont_exist/collections/'.$collectionId.'/attributes/'.$key.'/unknown_'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); @@ -3245,10 +3241,10 @@ class DatabasesCustomServerTest extends Scope /** * Check if Collection exists */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/i_dont_exist/attributes/' . $key . '/unknown_' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/i_dont_exist/attributes/'.$key.'/unknown_'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); @@ -3257,10 +3253,10 @@ class DatabasesCustomServerTest extends Scope /** * Check if Attribute exists */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key . '/unknown_' . $key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key.'/unknown_'.$key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php index b1d197f010..7f28097e70 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -22,7 +22,7 @@ class DatabasesPermissionsGuestTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'InvalidDocumentDatabase', @@ -31,7 +31,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ @@ -41,7 +41,7 @@ class DatabasesPermissionsGuestTest extends Scope Permission::delete(Role::any()), ], ]); - $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [], @@ -51,12 +51,12 @@ class DatabasesPermissionsGuestTest extends Scope $publicCollection = ['id' => $publicMovies['body']['$id']]; $privateCollection = ['id' => $privateMovies['body']['$id']]; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollection['id'] . '/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$publicCollection['id'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollection['id'] . '/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollection['id'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -93,14 +93,14 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', $this->getServerHeader(), [ + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], 'permissions' => $permissions, ]); - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -114,11 +114,11 @@ class DatabasesPermissionsGuestTest extends Scope $roles = Authorization::getRoles(); Authorization::cleanRoles(); - $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ + $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - $privateDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', [ + $privateDocuments = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -148,20 +148,20 @@ class DatabasesPermissionsGuestTest extends Scope $roles = Authorization::getRoles(); Authorization::cleanRoles(); - $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', - ] + ], ]); $publicDocumentId = $publicResponse['body']['$id']; $this->assertEquals(201, $publicResponse['headers']['status-code']); - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -174,7 +174,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateResponse['headers']['status-code']); // Create a document in private collection with API key so we can test that update and delete are also not allowed - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -184,7 +184,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $privateResponse['headers']['status-code']); $privateDocumentId = $privateResponse['body']['$id']; - $publicDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents/' . $publicDocumentId, [ + $publicDocument = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents/'.$publicDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -196,7 +196,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(200, $publicDocument['headers']['status-code']); $this->assertEquals('Thor: Ragnarok', $publicDocument['body']['title']); - $privateDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents/' . $privateDocumentId, [ + $privateDocument = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents/'.$privateDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -207,14 +207,14 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); - $publicDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents/' . $publicDocumentId, [ + $publicDocument = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents/'.$publicDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(204, $publicDocument['headers']['status-code']); - $privateDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents/' . $privateDocumentId, [ + $privateDocument = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents/'.$privateDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -231,7 +231,7 @@ class DatabasesPermissionsGuestTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'GuestPermissionsWrite', @@ -240,18 +240,18 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals('GuestPermissionsWrite', $database['body']['name']); $databaseId = $database['body']['$id']; - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::create(Role::any()), ], - 'documentSecurity' => true + 'documentSecurity' => true, ]); $moviesId = $movies['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -259,7 +259,7 @@ class DatabasesPermissionsGuestTest extends Scope sleep(1); - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -269,7 +269,7 @@ class DatabasesPermissionsGuestTest extends Scope ], 'permissions' => [ Permission::read(Role::any()), - ] + ], ]); $this->assertEquals(201, $document['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php index 860fb7fb12..73393b7efa 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php @@ -110,6 +110,7 @@ class DatabasesPermissionsMemberTest extends Scope * Data providers lose object state so explicitly pass [$users, $collections] to each iteration * * @return array + * * @throws \Exception */ public function testSetupDatabase(): array @@ -124,7 +125,7 @@ class DatabasesPermissionsMemberTest extends Scope $databaseId = $db['body']['$id']; - $public = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + $public = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ @@ -138,14 +139,14 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $public['headers']['status-code']); $this->collections = ['public' => $public['body']['$id']]; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['public'] . '/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$this->collections['public'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); $this->assertEquals(202, $response['headers']['status-code']); - $private = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + $private = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Private Movies', 'permissions' => [ @@ -159,14 +160,14 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $private['headers']['status-code']); $this->collections['private'] = $private['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['private'] . '/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$this->collections['private'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); $this->assertEquals(202, $response['headers']['status-code']); - $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + $doconly = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Document Only Movies', 'permissions' => [], @@ -175,7 +176,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $private['headers']['status-code']); $this->collections['doconly'] = $doconly['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['doconly'] . '/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$this->collections['doconly'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -187,12 +188,13 @@ class DatabasesPermissionsMemberTest extends Scope return [ 'users' => $this->users, 'collections' => $this->collections, - 'databaseId' => $databaseId + 'databaseId' => $databaseId, ]; } /** * Data provider params are passed before test dependencies + * * @dataProvider permissionsProvider * @depends testSetupDatabase */ @@ -202,41 +204,41 @@ class DatabasesPermissionsMemberTest extends Scope $collections = $data['collections']; $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collections['public'].'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], - 'permissions' => $permissions + 'permissions' => $permissions, ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collections['private'].'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], - 'permissions' => $permissions + 'permissions' => $permissions, ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collections['doconly'].'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], - 'permissions' => $permissions + 'permissions' => $permissions, ]); $this->assertEquals(201, $response['headers']['status-code']); /** * Check "any" permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collections['public'].'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users['user1']['session'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -245,11 +247,11 @@ class DatabasesPermissionsMemberTest extends Scope /** * Check "users" permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collections['private'].'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users['user1']['session'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -258,11 +260,11 @@ class DatabasesPermissionsMemberTest extends Scope /** * Check "user:user1" document only permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collections['doconly'].'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users['user1']['session'], ]); $this->assertEquals(200, $documents['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php b/tests/e2e/Services/Databases/DatabasesPermissionsScope.php index 181231adc5..a78153cf7d 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsScope.php @@ -7,6 +7,7 @@ use Tests\E2E\Client; trait DatabasesPermissionsScope { public array $users = []; + public array $teams = []; public function createUser(string $id, string $email, string $password = 'test123!'): array @@ -18,7 +19,7 @@ trait DatabasesPermissionsScope ], [ 'userId' => $id, 'email' => $email, - 'password' => $password + 'password' => $password, ]); $this->assertEquals(201, $user['headers']['status-code']); @@ -32,7 +33,7 @@ trait DatabasesPermissionsScope 'password' => $password, ]); - $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $user = [ '$id' => $user['body']['$id'], @@ -53,7 +54,7 @@ trait DatabasesPermissionsScope { $team = $this->client->call(Client::METHOD_POST, '/teams', $this->getServerHeader(), [ 'teamId' => $id, - 'name' => $name + 'name' => $name, ]); $this->teams[$id] = $team['body']; @@ -62,16 +63,16 @@ trait DatabasesPermissionsScope public function addToTeam(string $user, string $team, array $roles = []): array { - $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team . '/memberships', $this->getServerHeader(), [ + $membership = $this->client->call(Client::METHOD_POST, '/teams/'.$team.'/memberships', $this->getServerHeader(), [ 'teamId' => $team, 'email' => $this->getCreatedUser($user)['email'], 'roles' => $roles, - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); return [ 'user' => $membership['body']['userId'], - 'membership' => $membership['body']['$id'] + 'membership' => $membership['body']['$id'], ]; } @@ -80,7 +81,7 @@ trait DatabasesPermissionsScope return [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]; } } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php index dcbf3e4bff..e592902ab8 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -17,6 +17,7 @@ class DatabasesPermissionsTeamTest extends Scope use DatabasesPermissionsScope; public array $collections = []; + public string $databaseId = 'testpermissiondb'; public function createTeams(): array @@ -44,7 +45,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $this->assertEquals(201, $db['headers']['status-code']); - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::custom('collection1'), 'name' => 'Collection 1', 'permissions' => [ @@ -57,13 +58,13 @@ class DatabasesPermissionsTeamTest extends Scope $this->collections['collection1'] = $collection1['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection1'] . '/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection1'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections', $this->getServerHeader(), [ 'collectionId' => ID::custom('collection2'), 'name' => 'Collection 2', 'permissions' => [ @@ -71,12 +72,12 @@ class DatabasesPermissionsTeamTest extends Scope Permission::create(Role::team($teams['team2']['$id'], 'owner')), Permission::update(Role::team($teams['team2']['$id'], 'owner')), Permission::delete(Role::team($teams['team2']['$id'], 'owner')), - ] + ], ]); $this->collections['collection2'] = $collection2['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection2'] . '/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection2'].'/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -124,6 +125,7 @@ class DatabasesPermissionsTeamTest extends Scope * * Data providers lose object state * so explicitly pass $users to each iteration + * * @return array $users */ public function testSetupDatabase(): array @@ -140,7 +142,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->createCollections($this->teams); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection1'] . '/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection1'].'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -148,7 +150,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection2'] . '/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection2'].'/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', @@ -161,16 +163,17 @@ class DatabasesPermissionsTeamTest extends Scope /** * Data provider params are passed before test dependencies + * * @depends testSetupDatabase * @dataProvider readDocumentsProvider */ public function testReadDocuments($user, $collection, $success, $users) { - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $this->databaseId . '/collections/' . $collection . '/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$this->databaseId.'/collections/'.$collection.'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users[$user]['session'], ]); if ($success) { @@ -186,11 +189,11 @@ class DatabasesPermissionsTeamTest extends Scope */ public function testWriteDocuments($user, $collection, $success, $users) { - $documents = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $collection . '/documents', [ + $documents = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$collection.'/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users[$user]['session'], ], [ 'documentId' => ID::unique(), 'data' => [ diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index c45ebbe068..ad41ab7e47 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -8,11 +8,12 @@ use Utopia\CLI\Console; trait FunctionsBase { protected string $stdout = ''; + protected string $stderr = ''; protected function packageCode($folder) { - Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr); + Console::execute('cd '.realpath(__DIR__.'/../../../resources/functions')."/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr); } // /** diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index e28bdd233f..fec65fd3b9 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -2,9 +2,9 @@ namespace Tests\E2E\Services\Functions; -use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -41,13 +41,13 @@ class FunctionsConsoleClientTest extends Scope 'functionId' => ID::unique(), 'name' => 'Test Failure', 'execute' => ['some-random-string'], - 'runtime' => 'php-8.0' + 'runtime' => 'php-8.0', ]); $this->assertEquals(400, $response['headers']['status-code']); return [ - 'functionId' => $function['body']['$id'] + 'functionId' => $function['body']['$id'], ]; } @@ -59,21 +59,20 @@ class FunctionsConsoleClientTest extends Scope /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '232h' + 'range' => '232h', ]); $this->assertEquals(400, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_GET, '/functions/randomFunctionId/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -81,12 +80,11 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -109,13 +107,12 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST', - 'value' => 'TESTINGVALUE' + 'value' => 'TESTINGVALUE', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -124,13 +121,12 @@ class FunctionsConsoleClientTest extends Scope /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST', - 'value' => 'ANOTHER_TESTINGVALUE' + 'value' => 'ANOTHER_TESTINGVALUE', ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -138,28 +134,28 @@ class FunctionsConsoleClientTest extends Scope return array_merge( $data, [ - 'variableId' => $variableId + 'variableId' => $variableId, ] ); - $longKey = str_repeat("A", 256); - $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $longKey = str_repeat('A', 256); + $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => $longKey, - 'value' => 'TESTINGVALUE' + 'value' => 'TESTINGVALUE', ]); $this->assertEquals(400, $response['headers']['status-code']); - $longValue = str_repeat("#", 8193); - $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $longValue = str_repeat('#', 8193); + $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'LONGKEY', - 'value' => $longValue + 'value' => $longValue, ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -173,17 +169,16 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, sizeof($response['body']['variables'])); + $this->assertEquals(1, count($response['body']['variables'])); $this->assertEquals(1, $response['body']['total']); - $this->assertEquals("APP_TEST", $response['body']['variables'][0]['key']); - $this->assertEquals("TESTINGVALUE", $response['body']['variables'][0]['value']); + $this->assertEquals('APP_TEST', $response['body']['variables'][0]['key']); + $this->assertEquals('TESTINGVALUE', $response['body']['variables'][0]['value']); /** * Test for FAILURE @@ -200,21 +195,19 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals("APP_TEST", $response['body']['key']); - $this->assertEquals("TESTINGVALUE", $response['body']['value']); + $this->assertEquals('APP_TEST', $response['body']['key']); + $this->assertEquals('TESTINGVALUE', $response['body']['value']); /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/NON_EXISTING_VARIABLE', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/NON_EXISTING_VARIABLE', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -232,29 +225,28 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST_UPDATE', - 'value' => 'TESTINGVALUEUPDATED' + 'value' => 'TESTINGVALUEUPDATED', ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals("APP_TEST_UPDATE", $response['body']['key']); - $this->assertEquals("TESTINGVALUEUPDATED", $response['body']['value']); + $this->assertEquals('APP_TEST_UPDATE', $response['body']['key']); + $this->assertEquals('TESTINGVALUEUPDATED', $response['body']['value']); - $variable = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $variable = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $variable['headers']['status-code']); - $this->assertEquals("APP_TEST_UPDATE", $variable['body']['key']); - $this->assertEquals("TESTINGVALUEUPDATED", $variable['body']['value']); + $this->assertEquals('APP_TEST_UPDATE', $variable['body']['key']); + $this->assertEquals('TESTINGVALUEUPDATED', $variable['body']['value']); - $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -262,56 +254,55 @@ class FunctionsConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals("APP_TEST_UPDATE_2", $response['body']['key']); - $this->assertEquals("TESTINGVALUEUPDATED", $response['body']['value']); + $this->assertEquals('APP_TEST_UPDATE_2', $response['body']['key']); + $this->assertEquals('TESTINGVALUEUPDATED', $response['body']['value']); - $variable = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $variable = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $variable['headers']['status-code']); - $this->assertEquals("APP_TEST_UPDATE_2", $variable['body']['key']); - $this->assertEquals("TESTINGVALUEUPDATED", $variable['body']['value']); + $this->assertEquals('APP_TEST_UPDATE_2', $variable['body']['key']); + $this->assertEquals('TESTINGVALUEUPDATED', $variable['body']['value']); /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'value' => 'TESTINGVALUEUPDATED_2' + 'value' => 'TESTINGVALUEUPDATED_2', ]); $this->assertEquals(400, $response['headers']['status-code']); - $longKey = str_repeat("A", 256); - $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $longKey = str_repeat('A', 256); + $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => $longKey, - 'value' => 'TESTINGVALUEUPDATED' + 'value' => 'TESTINGVALUEUPDATED', ]); $this->assertEquals(400, $response['headers']['status-code']); - $longValue = str_repeat("#", 8193); - $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $longValue = str_repeat('#', 8193); + $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST_UPDATE', - 'value' => $longValue + 'value' => $longValue, ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -327,28 +318,26 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(0, sizeof($response['body']['variables'])); + $this->assertEquals(0, count($response['body']['variables'])); $this->assertEquals(0, $response['body']['total']); /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/variables/NON_EXISTING_VARIABLE', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/variables/NON_EXISTING_VARIABLE', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 713814e17f..b92308d348 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -65,7 +65,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/variables', [ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -74,7 +74,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/variables', [ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -83,7 +83,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/variables', [ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -97,17 +97,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $variable3['headers']['status-code']); $folder = 'php'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -117,7 +117,7 @@ class FunctionsCustomClientTest extends Scope // Wait for deployment to be built. sleep(20); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $function['body']['$id'] . '/deployments/' . $deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$function['body']['$id'].'/deployments/'.$deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -125,7 +125,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -134,7 +134,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(401, $execution['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -144,7 +144,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $execution['headers']['status-code']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $function['body']['$id'], [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$function['body']['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -180,7 +180,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -189,7 +189,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -198,7 +198,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -212,17 +212,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $variable3['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -232,7 +232,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -240,12 +240,12 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true + 'async' => true, ]); $this->assertEquals(202, $execution['headers']['status-code']); @@ -254,7 +254,7 @@ class FunctionsCustomClientTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -277,7 +277,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals($projectId, $output['APPWRITE_FUNCTION_PROJECT_ID']); return [ - 'functionId' => $functionId + 'functionId' => $functionId, ]; } @@ -311,17 +311,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -332,7 +332,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); // Why do we have to do this? - $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -340,7 +340,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], [ @@ -365,7 +365,7 @@ class FunctionsCustomClientTest extends Scope 'timeout' => 10, ]); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -386,19 +386,19 @@ class FunctionsCustomClientTest extends Scope $projectId = $this->getProject()['$id']; $apikey = $this->getProject()['apiKey']; - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true + 'async' => true, ]); $this->assertEquals(202, $execution['headers']['status-code']); sleep(20); - $base = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $base = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -409,71 +409,71 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('completed', $base['body']['executions'][0]['status']); $this->assertEquals('completed', $base['body']['executions'][1]['status']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => [ 'limit(1)' ] + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(1, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => [ 'offset(1)' ] + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(1, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => [ 'equal("status", ["completed"])' ] + 'queries' => ['equal("status", ["completed"])'], ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(2, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => [ 'equal("status", ["failed"])' ] + 'queries' => ['equal("status", ["failed"])'], ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(0, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => [ 'cursorAfter("' . $base['body']['executions'][0]['$id'] . '")' ], + 'queries' => ['cursorAfter("'.$base['body']['executions'][0]['$id'].'")'], ]); $this->assertCount(1, $executions['body']['executions']); $this->assertEquals($base['body']['executions'][1]['$id'], $executions['body']['executions'][0]['$id']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => [ 'cursorBefore("' . $base['body']['executions'][1]['$id'] . '")' ], + 'queries' => ['cursorBefore("'.$base['body']['executions'][1]['$id'].'")'], ]); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -487,7 +487,6 @@ class FunctionsCustomClientTest extends Scope /** * Test for SUCCESS */ - $projectId = $this->getProject()['$id']; $apikey = $this->getProject()['apiKey']; @@ -508,7 +507,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -517,7 +516,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -526,7 +525,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -540,17 +539,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $variable3['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -560,7 +559,7 @@ class FunctionsCustomClientTest extends Scope // Wait for deployment to be built. sleep(20); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -568,7 +567,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ @@ -596,7 +595,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEmpty($execution['body']['stderr']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index ab931f14e4..6ad1e578cb 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -8,7 +8,6 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -56,7 +55,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(10, $response1['body']['timeout']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -64,7 +63,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -72,7 +71,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -109,7 +108,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => $data['functionId'] + 'search' => $data['functionId'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -120,7 +119,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ] + 'queries' => ['limit(1)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -130,7 +129,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ] + 'queries' => ['offset(1)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -140,7 +139,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("enabled", true)' ] + 'queries' => ['equal("enabled", true)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -150,7 +149,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("enabled", false)' ] + 'queries' => ['equal("enabled", false)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -160,7 +159,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Test' + 'search' => 'Test', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -171,7 +170,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'php-8.0' + 'search' => 'php-8.0', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -198,7 +197,7 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($response['body']['$id']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $response['body']['$id'] . '/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$response['body']['$id'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -206,7 +205,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $response['body']['$id'] . '/variables', array_merge([ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$response['body']['$id'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -214,7 +213,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $response['body']['$id'] . '/variables', array_merge([ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$response['body']['$id'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -242,7 +241,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("' . $functions['body']['functions'][0]['$id'] . '")' ], + 'queries' => ['cursorAfter("'.$functions['body']['functions'][0]['$id'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -253,7 +252,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorBefore("' . $functions['body']['functions'][1]['$id'] . '")' ], + 'queries' => ['cursorBefore("'.$functions['body']['functions'][1]['$id'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -267,7 +266,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("unknown")' ], + 'queries' => ['cursorAfter("unknown")'], ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -283,7 +282,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -312,7 +311,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $response1 = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([ + $response1 = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -355,16 +354,16 @@ class FunctionsCustomServerTest extends Scope * Test for SUCCESS */ $folder = 'php'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -388,31 +387,30 @@ class FunctionsCustomServerTest extends Scope /** * Test for Large Code File SUCCESS */ - $folder = 'php-large'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); $chunkSize = 5 * 1024 * 1024; - $handle = @fopen($code, "rb"); + $handle = @fopen($code, 'rb'); $mimeType = 'application/x-gzip'; $counter = 0; $size = filesize($code); $headers = [ 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ]; $id = ''; - while (!feof($handle)) { - $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'php-large-fx.tar.gz'); - $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; - if (!empty($id)) { + while (! feof($handle)) { + $curlFile = new \CURLFile('data://'.$mimeType.';base64,'.base64_encode(@fread($handle, $chunkSize)), $mimeType, 'php-large-fx.tar.gz'); + $headers['content-range'] = 'bytes '.($counter * $chunkSize).'-'.min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1).'/'.$size; + if (! empty($id)) { $headers['x-appwrite-id'] = $id; } - $largeTag = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge($headers, $this->getHeaders()), [ + $largeTag = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge($headers, $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => $curlFile, - 'activate' => true + 'activate' => true, ]); $counter++; $id = $largeTag['body']['$id']; @@ -436,7 +434,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -463,7 +461,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -476,11 +474,11 @@ class FunctionsCustomServerTest extends Scope /** * Test search queries */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => $data['functionId'] + 'search' => $data['functionId'], ])); $this->assertEquals($function['headers']['status-code'], 200); @@ -489,51 +487,51 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(2, $function['body']['deployments']); $this->assertEquals($function['body']['deployments'][0]['$id'], $data['deploymentId']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ] + 'queries' => ['limit(1)'], ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(1, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ] + 'queries' => ['offset(1)'], ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(1, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("entrypoint", "index.php")' ] + 'queries' => ['equal("entrypoint", "index.php")'], ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(2, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("entrypoint", "index.js")' ] + 'queries' => ['equal("entrypoint", "index.js")'], ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(0, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => 'Test' + 'search' => 'Test', ])); $this->assertEquals($function['headers']['status-code'], 200); @@ -542,11 +540,11 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(2, $function['body']['deployments']); $this->assertEquals($function['body']['deployments'][0]['$id'], $data['deploymentId']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => 'php-8.0' + 'search' => 'php-8.0', ])); $this->assertEquals($function['headers']['status-code'], 200); @@ -566,7 +564,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -580,7 +578,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for FAILURE */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments/x', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments/x', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -598,7 +596,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -620,7 +618,7 @@ class FunctionsCustomServerTest extends Scope sleep(10); - $execution = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions/' . $executionId, array_merge([ + $execution = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/'.$executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -644,7 +642,6 @@ class FunctionsCustomServerTest extends Scope /** * Test for FAILURE */ - sleep(20); return array_merge($data, ['executionId' => $executionId]); @@ -658,7 +655,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -669,31 +666,31 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $function['body']['executions']); $this->assertEquals($function['body']['executions'][0]['$id'], $data['executionId']); - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ] + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(1, $response['body']['executions']); - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ] + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(0, $response['body']['executions']); - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("trigger", "http")' ] + 'queries' => ['equal("trigger", "http")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -702,8 +699,7 @@ class FunctionsCustomServerTest extends Scope /** * Test search queries */ - - $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $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()), [ @@ -716,7 +712,7 @@ class FunctionsCustomServerTest extends Scope $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([ + $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()), [ @@ -741,7 +737,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -769,7 +765,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions/' . $data['executionId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/'.$data['executionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -780,7 +776,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for FAILURE */ - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions/x', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/x', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -798,7 +794,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ + $function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -806,7 +802,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $function['headers']['status-code']); $this->assertEmpty($function['body']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -828,7 +824,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -836,7 +832,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $function['headers']['status-code']); $this->assertEmpty($function['body']); - $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -856,7 +852,7 @@ class FunctionsCustomServerTest extends Scope $entrypoint = 'index.php'; $timeout = 2; $folder = 'timeout'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ @@ -864,7 +860,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test ' . $name, + 'name' => 'Test '.$name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -874,7 +870,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -888,7 +884,7 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(40); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -901,7 +897,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -920,7 +916,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['stderr'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -938,7 +934,7 @@ class FunctionsCustomServerTest extends Scope $entrypoint = 'index.php'; $timeout = 2; $folder = 'php-fn'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ @@ -946,7 +942,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test ' . $name, + 'name' => 'Test '.$name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -956,13 +952,13 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => $entrypoint, 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -971,19 +967,19 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(20); - $deployment = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ + $deployment = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); $this->assertEquals(200, $deployment['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true + 'async' => true, ]); $executionId = $execution['body']['$id'] ?? ''; @@ -994,7 +990,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1004,7 +1000,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1017,7 +1013,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); $this->assertStringContainsString('Amazing Function Log', $executions['body']['stdout']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1031,7 +1027,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1040,12 +1036,11 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } - public function testCreateCustomNodeExecution() { $name = 'node-18.0'; $folder = 'node'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); $entrypoint = 'index.js'; @@ -1056,7 +1051,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test ' . $name, + 'name' => 'Test '.$name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -1067,7 +1062,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); // Create variable - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1077,7 +1072,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1092,12 +1087,12 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(20); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true + 'async' => true, ]); $executionId = $execution['body']['$id'] ?? ''; @@ -1108,7 +1103,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1118,7 +1113,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('Node.js', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1130,7 +1125,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1144,7 +1139,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1157,7 +1152,7 @@ class FunctionsCustomServerTest extends Scope { $name = 'python-3.9'; $folder = 'python'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); $entrypoint = 'main.py'; @@ -1168,7 +1163,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test ' . $name, + 'name' => 'Test '.$name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -1179,7 +1174,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1189,7 +1184,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1204,12 +1199,12 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(60); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true + 'async' => true, ]); $executionId = $execution['body']['$id'] ?? ''; @@ -1220,7 +1215,7 @@ class FunctionsCustomServerTest extends Scope sleep(60); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1230,7 +1225,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('Python', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1243,7 +1238,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1257,7 +1252,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1383,7 +1378,7 @@ class FunctionsCustomServerTest extends Scope { $name = 'ruby-3.1'; $folder = 'ruby'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); $entrypoint = 'main.rb'; @@ -1394,7 +1389,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test ' . $name, + 'name' => 'Test '.$name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -1405,7 +1400,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1415,7 +1410,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1430,12 +1425,12 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(60); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true + 'async' => true, ]); $executionId = $execution['body']['$id'] ?? ''; @@ -1446,7 +1441,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1456,7 +1451,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('Ruby', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1468,7 +1463,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1482,7 +1477,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/AbuseTest.php index 48ee64d141..163f695811 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/AbuseTest.php @@ -92,7 +92,7 @@ class AbuseTest extends Scope $max = App::getEnv('_APP_GRAPHQL_MAX_QUERY_COMPLEXITY', 250); - $this->assertEquals('Max query complexity should be ' . $max . ' but got 259.', $response['body']['errors'][0]['message']); + $this->assertEquals('Max query complexity should be '.$max.' but got 259.', $response['body']['errors'][0]['message']); } public function testTooManyQueriesBlocked() @@ -122,7 +122,7 @@ class AbuseTest extends Scope 'variables' => [ 'databaseId' => 'actors', 'name' => 'AbuseDatabase', - ] + ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -145,7 +145,7 @@ class AbuseTest extends Scope Permission::read(Role::any()), Permission::write(Role::any()), ], - ] + ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -165,7 +165,7 @@ class AbuseTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ] + ], ]; $this->client->call(Client::METHOD_POST, '/graphql', [ diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 7fd70b5015..c77773cba9 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -18,7 +18,7 @@ class AccountTest extends Scope { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_ACCOUNT); - $email = 'test' . \rand() . '@test.com'; + $email = 'test'.\rand().'@test.com'; $graphQLPayload = [ 'query' => $query, 'variables' => [ @@ -51,7 +51,7 @@ class AccountTest extends Scope 'variables' => [ 'email' => $this->getUser()['email'], 'password' => 'password', - ] + ], ]; $session = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -63,7 +63,7 @@ class AccountTest extends Scope $this->assertIsArray($session['body']['data']); $this->assertIsArray($session['body']['data']['accountCreateEmailSession']); - $cookie = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $cookie = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertNotEmpty($cookie); } @@ -71,13 +71,13 @@ class AccountTest extends Scope { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_MAGIC_URL); - $email = 'test' . \rand() . '@test.com'; + $email = 'test'.\rand().'@test.com'; $graphQLPayload = [ 'query' => $query, 'variables' => [ 'userId' => ID::unique(), 'email' => $email, - ] + ], ]; $session = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -99,7 +99,7 @@ class AccountTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'url' => 'http://localhost/verification' + 'url' => 'http://localhost/verification', ], ]; @@ -117,7 +117,9 @@ class AccountTest extends Scope /** * @depends testUpdateAccountPhone + * * @return array + * * @throws \Exception */ public function testCreatePhoneVerification(): array @@ -274,7 +276,7 @@ class AccountTest extends Scope 'query' => $query, 'variables' => [ 'sessionId' => 'current', - ] + ], ]; $session = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -317,8 +319,8 @@ class AccountTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'name' => 'Tester Updated' - ] + 'name' => 'Tester Updated', + ], ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -343,7 +345,7 @@ class AccountTest extends Scope 'variables' => [ 'email' => 'newemail@appwrite.io', 'password' => 'password', - ] + ], ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -368,7 +370,7 @@ class AccountTest extends Scope 'variables' => [ 'oldPassword' => 'password', 'password' => 'password', - ] + ], ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -392,7 +394,7 @@ class AccountTest extends Scope 'variables' => [ 'phone' => '+123456789', 'password' => 'password', - ] + ], ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -440,9 +442,9 @@ class AccountTest extends Scope 'query' => $query, 'variables' => [ 'prefs' => [ - 'key' => 'value' - ] - ] + 'key' => 'value', + ], + ], ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -463,7 +465,7 @@ class AccountTest extends Scope $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$DELETE_ACCOUNT_SESSIONS); $graphQLPayload = [ - 'query' => $query + 'query' => $query, ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -488,7 +490,7 @@ class AccountTest extends Scope 'query' => $query, 'variables' => [ 'sessionId' => 'current', - ] + ], ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/AuthTest.php index c331fb8437..63177ee3bc 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/AuthTest.php @@ -7,8 +7,8 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Role; use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class AuthTest extends Scope { @@ -17,12 +17,15 @@ class AuthTest extends Scope use Base; private array $account1; + private array $account2; private string $token1; + private string $token2; private array $database; + private array $collection; public function setUp(): void @@ -32,8 +35,8 @@ class AuthTest extends Scope $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_ACCOUNT); - $email1 = 'test' . \rand() . '@test.com'; - $email2 = 'test' . \rand() . '@test.com'; + $email1 = 'test'.\rand().'@test.com'; + $email2 = 'test'.\rand().'@test.com'; // Create account 1 $graphQLPayload = [ @@ -66,7 +69,7 @@ class AuthTest extends Scope 'variables' => [ 'email' => $email1, 'password' => 'password', - ] + ], ]; $session1 = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -74,8 +77,8 @@ class AuthTest extends Scope ], $graphQLPayload); $this->token1 = $this->client->parseCookie( - (string)$session1['headers']['set-cookie'] - )['a_session_' . $projectId]; + (string) $session1['headers']['set-cookie'] + )['a_session_'.$projectId]; // Create session 2 $graphQLPayload['variables']['email'] = $email2; @@ -86,8 +89,8 @@ class AuthTest extends Scope ], $graphQLPayload); $this->token2 = $this->client->parseCookie( - (string)$session2['headers']['set-cookie'] - )['a_session_' . $projectId]; + (string) $session2['headers']['set-cookie'] + )['a_session_'.$projectId]; // Create database $query = $this->getQuery(self::$CREATE_DATABASE); @@ -96,7 +99,7 @@ class AuthTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ] + ], ]; $this->database = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -115,9 +118,9 @@ class AuthTest extends Scope 'name' => 'Actors', 'documentSecurity' => true, 'permissions' => [ - Permission::create(Role::user($userId)) - ] - ] + Permission::create(Role::user($userId)), + ], + ], ]; $this->collection = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -135,7 +138,7 @@ class AuthTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ] + ], ]; $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -166,13 +169,13 @@ class AuthTest extends Scope Permission::read(Role::user($userId)), Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), - ] - ] + ], + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + 'cookie' => 'a_session_'.$projectId.'='.$this->token1, ], $gqlPayload); // Try to read as account 1 @@ -183,12 +186,12 @@ class AuthTest extends Scope 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + 'cookie' => 'a_session_'.$projectId.'='.$this->token1, ], $gqlPayload); $this->assertIsArray($document['body']['data']['databasesGetDocument']); @@ -198,7 +201,7 @@ class AuthTest extends Scope $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $this->token2, + 'cookie' => 'a_session_'.$projectId.'='.$this->token2, ], $gqlPayload); $this->assertArrayHasKey('errors', $document['body']); @@ -226,12 +229,12 @@ class AuthTest extends Scope Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), ], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + 'cookie' => 'a_session_'.$projectId.'='.$this->token1, ], $gqlPayload); // Try to delete as account 1 @@ -242,12 +245,12 @@ class AuthTest extends Scope 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + 'cookie' => 'a_session_'.$projectId.'='.$this->token1, ], $gqlPayload); $this->assertIsNotArray($document['body']); diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 67d09bb4ac..8f16222f1e 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -6,195 +6,342 @@ trait Base { // Databases public static string $CREATE_DATABASE = 'create_database'; + public static string $GET_DATABASES = 'get_databases'; + public static string $GET_DATABASE = 'get_database'; + public static string $UPDATE_DATABASE = 'update_database'; + public static string $DELETE_DATABASE = 'delete_database'; + // Collections public static string $CREATE_COLLECTION = 'create_collection'; + public static string $GET_COLLECTION = 'get_collection'; + public static string $GET_COLLECTIONS = 'list_collections'; + public static string $UPDATE_COLLECTION = 'update_collection'; + public static string $DELETE_COLLECTION = 'delete_collection'; + // Attributes public static string $CREATE_STRING_ATTRIBUTE = 'create_string_attribute'; + public static string $CREATE_INTEGER_ATTRIBUTE = 'create_integer_attribute'; + public static string $CREATE_FLOAT_ATTRIBUTE = 'create_float_attribute'; + public static string $CREATE_BOOLEAN_ATTRIBUTE = 'create_boolean_attribute'; + public static string $CREATE_URL_ATTRIBUTE = 'create_url_attribute'; + public static string $CREATE_EMAIL_ATTRIBUTE = 'create_email_attribute'; + public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute'; + public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute'; + public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute'; public static string $CREATE_RELATIONSHIP_ATTRIBUTE = 'create_relationship_attribute'; + public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute'; + public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute'; + public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute'; + public static string $UPDATE_BOOLEAN_ATTRIBUTE = 'update_boolean_attribute'; + public static string $UPDATE_URL_ATTRIBUTE = 'update_url_attribute'; + public static string $UPDATE_EMAIL_ATTRIBUTE = 'update_email_attribute'; + public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute'; + public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute'; + public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute'; public static string $UPDATE_RELATIONSHIP_ATTRIBUTE = 'update_relationship_attribute'; + public static string $GET_ATTRIBUTES = 'get_attributes'; + public static string $GET_ATTRIBUTE = 'get_attribute'; + public static string $DELETE_ATTRIBUTE = 'delete_attribute'; + // Indexes public static string $CREATE_INDEX = 'create_index'; + public static string $GET_INDEXES = 'get_indexes'; + public static string $GET_INDEX = 'get_index'; + public static string $DELETE_INDEX = 'delete_index'; + // Documents public static string $CREATE_DOCUMENT = 'create_document_rest'; + public static string $GET_DOCUMENTS = 'list_documents'; + public static string $GET_DOCUMENT = 'get_document'; + public static string $UPDATE_DOCUMENT = 'update_document'; + public static string $DELETE_DOCUMENT = 'delete_document'; // Custom Entities public static string $CREATE_CUSTOM_ENTITY = 'create_custom_entity'; + public static string $GET_CUSTOM_ENTITIES = 'get_custom_entities'; + public static string $GET_CUSTOM_ENTITY = 'get_custom_entity'; + public static string $UPDATE_CUSTOM_ENTITY = 'update_custom_entity'; + public static string $DELETE_CUSTOM_ENTITY = 'delete_custom_entity'; // Account public static string $CREATE_ACCOUNT = 'create_account'; + public static string $CREATE_ACCOUNT_SESSION = 'create_account_session'; + public static string $CREATE_ANONYMOUS_SESSION = 'create_anonymous_session'; + public static string $CREATE_ACCOUNT_JWT = 'create_account_jwt'; + public static string $CREATE_MAGIC_URL = 'create_magic_url'; + public static string $CREATE_PASSWORD_RECOVERY = 'create_password_recovery'; + public static string $CREATE_EMAIL_VERIFICATION = 'create_email_verification'; + public static string $CREATE_PHONE_VERIFICATION = 'create_phone_verification'; + public static string $GET_ACCOUNT = 'get_account'; + public static string $GET_ACCOUNT_SESSION = 'get_account_session'; + public static string $GET_ACCOUNT_SESSIONS = 'get_account_sessions'; + public static string $GET_ACCOUNT_PREFS = 'get_account_preferences'; + public static string $GET_ACCOUNT_LOGS = 'get_account_logs'; + public static string $UPDATE_ACCOUNT_NAME = 'update_account_name'; + public static string $UPDATE_ACCOUNT_EMAIL = 'update_account_email'; + public static string $UPDATE_ACCOUNT_PASSWORD = 'update_account_password'; + public static string $UPDATE_ACCOUNT_PREFS = 'update_account_prefs'; + public static string $UPDATE_ACCOUNT_PHONE = 'update_account_phone'; + public static string $UPDATE_ACCOUNT_STATUS = 'update_account_status'; + public static string $UPDATE_MAGIC_URL = 'confirm_magic_url'; + public static string $UPDATE_PASSWORD_RECOVERY = 'confirm_password_recovery'; + public static string $UPDATE_EMAIL_VERIFICATION = 'confirm_email_verification'; + public static string $UPDATE_PHONE_VERIFICATION = 'confirm_phone_verification'; + public static string $DELETE_ACCOUNT_SESSION = 'delete_account_session'; + public static string $DELETE_ACCOUNT_SESSIONS = 'delete_account_sessions'; // Users public static string $CREATE_USER = 'create_user'; + public static string $GET_USER = 'get_user'; + public static string $GET_USERS = 'list_user'; + public static string $GET_USER_PREFERENCES = 'get_user_preferences'; + public static string $GET_USER_SESSIONS = 'get_user_sessions'; + public static string $GET_USER_MEMBERSHIPS = 'get_user_memberships'; + public static string $GET_USER_LOGS = 'get_user_logs'; + public static string $UPDATE_USER_STATUS = 'update_user_status'; + public static string $UPDATE_USER_NAME = 'update_user_name'; + public static string $UPDATE_USER_EMAIL = 'update_user_email'; + public static string $UPDATE_USER_EMAIL_VERIFICATION = 'update_email_verification'; + public static string $UPDATE_USER_PHONE_VERIFICATION = 'update_phone_verification'; + public static string $UPDATE_USER_PASSWORD = 'update_user_password'; + public static string $UPDATE_USER_PHONE = 'update_user_phone'; + public static string $UPDATE_USER_PREFS = 'update_user_prefs'; + public static string $DELETE_USER_SESSIONS = 'delete_user_sessions'; + public static string $DELETE_USER_SESSION = 'delete_user_session'; + public static string $DELETE_USER = 'delete_user'; // Teams public static string $GET_TEAM = 'get_team'; + public static string $GET_TEAM_PREFERENCES = 'get_team_preferences'; + public static string $GET_TEAMS = 'list_teams'; + public static string $CREATE_TEAM = 'create_team'; + public static string $UPDATE_TEAM_NAME = 'update_team_name'; + public static string $UPDATE_TEAM_PREFERENCES = 'update_team_preferences'; public static string $DELETE_TEAM = 'delete_team'; + public static string $GET_TEAM_MEMBERSHIP = 'get_team_membership'; + public static string $GET_TEAM_MEMBERSHIPS = 'list_team_memberships'; + public static string $CREATE_TEAM_MEMBERSHIP = 'create_team_membership'; + public static string $UPDATE_TEAM_MEMBERSHIP = 'update_team_membership'; + public static string $UPDATE_TEAM_MEMBERSHIP_STATUS = 'update_membership_status'; + public static string $DELETE_TEAM_MEMBERSHIP = 'delete_team_membership'; // Functions public static string $CREATE_FUNCTION = 'create_function'; + public static string $GET_FUNCTIONS = 'list_functions'; + public static string $GET_FUNCTION = 'get_function'; + public static string $GET_RUNTIMES = 'list_runtimes'; + public static string $UPDATE_FUNCTION = 'update_function'; + public static string $DELETE_FUNCTION = 'delete_function'; + // Variables public static string $CREATE_VARIABLE = 'create_variable'; + public static string $GET_VARIABLES = 'list_variables'; + public static string $GET_VARIABLE = 'get_variable'; + public static string $UPDATE_VARIABLE = 'update_variable'; + public static string $DELETE_VARIABLE = 'delete_variable'; //Deployments public static string $CREATE_DEPLOYMENT = 'create_deployment'; + public static string $GET_DEPLOYMENTS = 'list_deployments'; + public static string $GET_DEPLOYMENT = 'get_deployment'; + public static string $UPDATE_DEPLOYMENT = 'update_deployment'; + public static string $DELETE_DEPLOYMENT = 'delete_deployment'; + // Executions public static string $GET_EXECUTIONS = 'list_executions'; + public static string $GET_EXECUTION = 'get_execution'; + public static string $CREATE_EXECUTION = 'create_execution'; + public static string $DELETE_EXECUTION = 'delete_execution'; + public static string $RETRY_BUILD = 'retry_build'; // Buckets public static string $CREATE_BUCKET = 'create_bucket'; + public static string $GET_BUCKETS = 'list_buckets'; + public static string $GET_BUCKET = 'get_bucket'; + public static string $UPDATE_BUCKET = 'update_bucket'; + public static string $DELETE_BUCKET = 'delete_bucket'; + // Files public static string $CREATE_FILE = 'create_file'; + public static string $GET_FILES = 'list_files'; + public static string $GET_FILE = 'get_file'; + public static string $GET_FILE_PREVIEW = 'get_file_preview'; + public static string $GET_FILE_DOWNLOAD = 'get_file_download'; + public static string $GET_FILE_VIEW = 'get_file_view'; + public static string $UPDATE_FILE = 'update_file'; + public static string $DELETE_FILE = 'delete_file'; // Health public static string $GET_HTTP_HEALTH = 'get_http_health'; + public static string $GET_DB_HEALTH = 'get_db_health'; + public static string $GET_CACHE_HEALTH = 'get_cache_health'; + public static string $GET_TIME_HEALTH = 'get_time_health'; + public static string $GET_WEBHOOKS_QUEUE_HEALTH = 'get_webhooks_queue_health'; + public static string $GET_LOGS_QUEUE_HEALTH = 'get_logs_queue_health'; + public static string $GET_CERTIFICATES_QUEUE_HEALTH = 'get_certificates_queue_health'; + public static string $GET_FUNCTION_QUEUE_HEALTH = 'get_functions_queue_health'; + public static string $GET_LOCAL_STORAGE_HEALTH = 'get_local_storage_health'; + public static string $GET_ANITVIRUS_HEALTH = 'get_antivirus_health'; // Localization public static string $GET_LOCALE = 'get_locale'; + public static string $LIST_COUNTRIES = 'list_countries'; + public static string $LIST_EU_COUNTRIES = 'list_eu_countries'; + public static string $LIST_COUNTRY_PHONE_CODES = 'list_country_phone_codes'; + public static string $LIST_CONTINENTS = 'list_continents'; + public static string $LIST_CURRENCIES = 'list_currencies'; + public static string $LIST_LANGUAGES = 'list_languages'; // Avatars public static string $GET_CREDIT_CARD_ICON = 'get_credit_card_icon'; + public static string $GET_BROWSER_ICON = 'get_browser_icon'; + public static string $GET_COUNTRY_FLAG = 'get_country_flag'; + public static string $GET_IMAGE_FROM_URL = 'get_image_from_url'; + public static string $GET_FAVICON = 'get_favicon'; + public static string $GET_QRCODE = 'get_qrcode'; + public static string $GET_USER_INITIALS = 'get_user_initials'; // Complex queries @@ -598,13 +745,13 @@ trait Base ...attributeProperties } } - }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + }'.PHP_EOL.self::$FRAGMENT_ATTRIBUTES; case self::$GET_ATTRIBUTE: return 'query getAttribute($databaseId: String!, $collectionId: String!, $key: String!) { databasesGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { ...attributeProperties } - }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + }'.PHP_EOL.self::$FRAGMENT_ATTRIBUTES; case self::$DELETE_ATTRIBUTE: return 'mutation deleteAttribute($databaseId: String!, $collectionId: String!, $key: String!) { databasesDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { @@ -728,7 +875,7 @@ trait Base ...options } } - }' . PHP_EOL . self::$FRAGMENT_HASH_OPTIONS; + }'.PHP_EOL.self::$FRAGMENT_HASH_OPTIONS; case self::$GET_USER_PREFERENCES: return 'query getUserPreferences($userId : String!) { usersGetPrefs(userId : $userId) { @@ -1923,7 +2070,7 @@ trait Base data } } - }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + }'.PHP_EOL.self::$FRAGMENT_ATTRIBUTES; } throw new \InvalidArgumentException('Invalid query type'); diff --git a/tests/e2e/Services/GraphQL/BatchTest.php b/tests/e2e/Services/GraphQL/BatchTest.php index 7082d23677..a6f1da2908 100644 --- a/tests/e2e/Services/GraphQL/BatchTest.php +++ b/tests/e2e/Services/GraphQL/BatchTest.php @@ -63,7 +63,7 @@ class BatchTest extends Scope public function testArrayBatchedMutations() { $projectId = $this->getProject()['$id']; - $email = 'tester' . \uniqid() . '@example.com'; + $email = 'tester'.\uniqid().'@example.com'; $graphQLPayload = [[ 'query' => 'mutation CreateAccount($userId: String!, $email: String!, $password: String!, $name: String) { accountCreate(userId: $userId, email: $email, password: $password, name: $name) { @@ -77,17 +77,17 @@ class BatchTest extends Scope 'name' => 'Tester 1', ], ], - [ - 'query' => 'mutation CreateTeam($teamId: String! $name: String!) { + [ + 'query' => 'mutation CreateTeam($teamId: String! $name: String!) { teamsCreate(teamId: $teamId, name: $name) { name } }', - 'variables' => [ - 'teamId' => ID::unique(), - 'name' => 'Team 1', - ], - ]]; + 'variables' => [ + 'teamId' => ID::unique(), + 'name' => 'Team 1', + ], + ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', @@ -107,8 +107,8 @@ class BatchTest extends Scope public function testArrayBatchedMutationsOfSameType() { $projectId = $this->getProject()['$id']; - $email1 = 'tester' . \uniqid() . '@example.com'; - $email2 = 'tester' . \uniqid() . '@example.com'; + $email1 = 'tester'.\uniqid().'@example.com'; + $email2 = 'tester'.\uniqid().'@example.com'; $query = 'mutation CreateAccount($userId: String!, $email: String!, $password: String!, $name: String) { accountCreate(userId: $userId, email: $email, password: $password, name: $name) { _id @@ -152,7 +152,7 @@ class BatchTest extends Scope public function testArrayBatchedMixed() { $projectId = $this->getProject()['$id']; - $email = 'tester' . \uniqid() . '@example.com'; + $email = 'tester'.\uniqid().'@example.com'; $graphQLPayload = [ ['query' => 'query { localeListCountries { total countries { code } } }'], ['query' => 'query { localeListContinents { total continents { code } } }'], @@ -167,7 +167,7 @@ class BatchTest extends Scope 'email' => $email, 'password' => 'password', 'name' => 'Tester 1', - ] + ], ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -192,7 +192,7 @@ class BatchTest extends Scope public function testArrayBatchedMixedOfSameType() { $projectId = $this->getProject()['$id']; - $email = 'tester' . \uniqid() . '@example.com'; + $email = 'tester'.\uniqid().'@example.com'; $query = 'query { localeListCountries { total countries { code } } }'; $graphQLPayload = [ ['query' => $query], @@ -208,7 +208,7 @@ class BatchTest extends Scope 'email' => $email, 'password' => 'password', 'name' => 'Tester 1', - ] + ], ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -281,7 +281,7 @@ class BatchTest extends Scope public function testQueryBatchedMutations() { $projectId = $this->getProject()['$id']; - $email = 'tester' . \uniqid() . '@example.com'; + $email = 'tester'.\uniqid().'@example.com'; $graphQLPayload = [ 'query' => 'mutation CreateAndLogin($userId: String!, $email: String!, $password: String!, $name: String) { accountCreate(userId: $userId, email: $email, password: $password, name: $name) { @@ -304,7 +304,6 @@ class BatchTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $graphQLPayload); - $this->assertIsArray($response['body']['data']); $this->assertArrayNotHasKey('errors', $response['body']); $this->assertArrayHasKey('accountCreate', $response['body']['data']); @@ -315,8 +314,8 @@ class BatchTest extends Scope public function testQueryBatchedMutationsOfSameType() { $projectId = $this->getProject()['$id']; - $email1 = 'tester' . \uniqid() . '@example.com'; - $email2 = 'tester' . \uniqid() . '@example.com'; + $email1 = 'tester'.\uniqid().'@example.com'; + $email2 = 'tester'.\uniqid().'@example.com'; $graphQLPayload = [ 'query' => 'mutation CreateAndLogin($email1: String!, $email2: String!, $password: String!, $name1: String, $name2: String) { accountCreate(userId: "unique()", email: $email1, password: $password, name: $name1) { @@ -347,8 +346,8 @@ class BatchTest extends Scope public function testQueryBatchedMutationsOfSameTypeWithAlias() { $projectId = $this->getProject()['$id']; - $email1 = 'tester' . \uniqid() . '@example.com'; - $email2 = 'tester' . \uniqid() . '@example.com'; + $email1 = 'tester'.\uniqid().'@example.com'; + $email2 = 'tester'.\uniqid().'@example.com'; $graphQLPayload = [ 'query' => 'mutation CreateAndLogin($email1: String!, $email2: String!, $password: String!, $name1: String, $name2: String) { account1: accountCreate(userId: "unique()", email: $email1, password: $password, name: $name1) { diff --git a/tests/e2e/Services/GraphQL/ContentTypeTest.php b/tests/e2e/Services/GraphQL/ContentTypeTest.php index da885a2a83..5ab950d893 100644 --- a/tests/e2e/Services/GraphQL/ContentTypeTest.php +++ b/tests/e2e/Services/GraphQL/ContentTypeTest.php @@ -115,7 +115,7 @@ class ContentTypeTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', @@ -138,12 +138,12 @@ class ContentTypeTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]), 'map' => \json_encode([ - 'file' => ["variables.file"] + 'file' => ['variables.file'], ]), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/DatabaseClientTest.php index 3853a3fc17..ae3b908330 100644 --- a/tests/e2e/Services/GraphQL/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseClientTest.php @@ -25,7 +25,7 @@ class DatabaseClientTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -62,7 +62,7 @@ class DatabaseClientTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - ] + ], ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -97,7 +97,7 @@ class DatabaseClientTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -129,7 +129,7 @@ class DatabaseClientTest extends Scope 'min' => 18, 'max' => 150, 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -170,7 +170,7 @@ class DatabaseClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -193,6 +193,7 @@ class DatabaseClientTest extends Scope /** * @depends testCreateCollection + * * @throws \Exception */ public function testGetDocuments($data): void @@ -204,7 +205,7 @@ class DatabaseClientTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ] + ], ]; $documents = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -219,6 +220,7 @@ class DatabaseClientTest extends Scope /** * @depends testCreateDocument + * * @throws \Exception */ public function testGetDocument($data): void @@ -231,7 +233,7 @@ class DatabaseClientTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -246,6 +248,7 @@ class DatabaseClientTest extends Scope /** * @depends testCreateDocument + * * @throws \Exception */ public function testUpdateDocument($data): void @@ -261,7 +264,7 @@ class DatabaseClientTest extends Scope 'data' => [ 'name' => 'New Document Name', ], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -279,6 +282,7 @@ class DatabaseClientTest extends Scope /** * @depends testCreateDocument + * * @throws \Exception */ public function testDeleteDocument($data): void @@ -291,7 +295,7 @@ class DatabaseClientTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ diff --git a/tests/e2e/Services/GraphQL/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/DatabaseServerTest.php index 87006a1bea..f17159c174 100644 --- a/tests/e2e/Services/GraphQL/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseServerTest.php @@ -27,7 +27,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => 'actors', 'name' => 'Actors', - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -63,7 +63,7 @@ class DatabaseServerTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - ] + ], ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -89,7 +89,7 @@ class DatabaseServerTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - ] + ], ]; $collection2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -111,6 +111,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateStringAttribute($data): array @@ -125,7 +126,7 @@ class DatabaseServerTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -142,6 +143,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateStringAttribute + * * @throws Exception */ public function testUpdateStringAttribute($data): array @@ -159,7 +161,7 @@ class DatabaseServerTest extends Scope 'key' => 'name', 'required' => false, 'default' => 'Default Value', - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -178,6 +180,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateIntegerAttribute($data): array @@ -193,7 +196,7 @@ class DatabaseServerTest extends Scope 'min' => 18, 'max' => 150, 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -210,6 +213,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIntegerAttribute + * * @throws Exception */ public function testUpdateIntegerAttribute($data): array @@ -228,8 +232,8 @@ class DatabaseServerTest extends Scope 'required' => false, 'min' => 12, 'max' => 160, - 'default' => 50 - ] + 'default' => 50, + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -250,6 +254,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateBooleanAttribute($data): array @@ -263,7 +268,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'alive', 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -280,6 +285,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateBooleanAttribute + * * @throws Exception */ public function testUpdateBooleanAttribute($data): array @@ -296,8 +302,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'alive', 'required' => false, - 'default' => true - ] + 'default' => true, + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -316,6 +322,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateFloatAttribute($data): array @@ -332,7 +339,7 @@ class DatabaseServerTest extends Scope 'max' => 999999.99, 'default' => 1000.0, 'required' => false, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -349,6 +356,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateFloatAttribute + * * @throws Exception */ public function testUpdateFloatAttribute($data): array @@ -367,8 +375,8 @@ class DatabaseServerTest extends Scope 'required' => false, 'min' => 100.0, 'max' => 1000000.0, - 'default' => 2500.0 - ] + 'default' => 2500.0, + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -389,6 +397,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateEmailAttribute($data): array @@ -402,7 +411,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'email', 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -419,6 +428,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateEmailAttribute + * * @throws Exception */ public function testUpdateEmailAttribute($data): array @@ -436,7 +446,7 @@ class DatabaseServerTest extends Scope 'key' => 'email', 'required' => false, 'default' => 'torsten@appwrite.io', - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -455,6 +465,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateEnumAttribute($data): array @@ -473,7 +484,7 @@ class DatabaseServerTest extends Scope 'guest', ], 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -488,9 +499,9 @@ class DatabaseServerTest extends Scope return $data; } - /** * @depends testCreateEnumAttribute + * * @throws Exception */ public function testUpdateEnumAttribute($data): array @@ -510,10 +521,10 @@ class DatabaseServerTest extends Scope 'elements' => [ 'crew', 'tech', - 'actor' + 'actor', ], - 'default' => 'tech' - ] + 'default' => 'tech', + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -534,6 +545,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateDatetimeAttribute($data): array @@ -547,7 +559,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'dob', 'required' => true, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -564,6 +576,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatetimeAttribute + * * @throws Exception */ public function testUpdateDatetimeAttribute($data): array @@ -580,8 +593,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'dob', 'required' => false, - 'default' => '2000-01-01T00:00:00Z' - ] + 'default' => '2000-01-01T00:00:00Z', + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -614,8 +627,8 @@ class DatabaseServerTest extends Scope 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'actors', - 'twoWayKey' => 'movie' - ] + 'twoWayKey' => 'movie', + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -646,7 +659,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection2']['_id'], 'key' => 'actors', 'onDelete' => Database::RELATION_MUTATE_CASCADE, - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -663,6 +676,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateIPAttribute($data): array @@ -677,7 +691,7 @@ class DatabaseServerTest extends Scope 'key' => 'ip', 'required' => false, 'default' => '::1', - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -694,6 +708,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIPAttribute + * * @throws Exception */ public function testUpdateIPAttribute($data): array @@ -710,8 +725,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'ip', 'required' => false, - 'default' => '127.0.0.1' - ] + 'default' => '127.0.0.1', + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -730,6 +745,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testCreateURLAttribute($data): array @@ -744,7 +760,7 @@ class DatabaseServerTest extends Scope 'key' => 'url', 'required' => false, 'default' => 'https://appwrite.io', - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -761,6 +777,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateURLAttribute + * * @throws Exception */ public function testUpdateURLAttribute($data): void @@ -777,8 +794,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'url', 'required' => false, - 'default' => 'https://cloud.appwrite.io' - ] + 'default' => 'https://cloud.appwrite.io', + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -796,6 +813,7 @@ class DatabaseServerTest extends Scope /** * @depends testUpdateStringAttribute * @depends testUpdateIntegerAttribute + * * @throws Exception */ public function testCreateIndex($data): array @@ -813,7 +831,7 @@ class DatabaseServerTest extends Scope 'name', 'age', ], - ] + ], ]; $index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -837,6 +855,7 @@ class DatabaseServerTest extends Scope * @depends testUpdateIntegerAttribute * @depends testUpdateBooleanAttribute * @depends testUpdateEnumAttribute + * * @throws Exception */ public function testCreateDocument($data): array @@ -863,7 +882,7 @@ class DatabaseServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -944,6 +963,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase + * * @throws Exception */ public function testGetDatabase($database): void @@ -954,7 +974,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -969,6 +989,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testGetCollections($data): void @@ -979,7 +1000,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - ] + ], ]; $collections = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -994,6 +1015,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testGetCollection($data): void @@ -1005,7 +1027,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ] + ], ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1021,6 +1043,7 @@ class DatabaseServerTest extends Scope /** * @depends testUpdateStringAttribute * @depends testUpdateIntegerAttribute + * * @throws Exception */ public function testGetAttributes($data): void @@ -1032,7 +1055,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ] + ], ]; $attributes = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1047,6 +1070,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testGetAttribute($data): void @@ -1059,7 +1083,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'key' => 'name', - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1074,6 +1098,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIndex + * * @throws Exception */ public function testGetIndexes($data): void @@ -1085,7 +1110,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ] + ], ]; $indices = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1100,6 +1125,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIndex + * * @throws Exception */ public function testGetIndex($data): void @@ -1112,7 +1138,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'key' => $data['index']['key'], - ] + ], ]; $index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1127,6 +1153,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testGetDocuments($data): void @@ -1138,7 +1165,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ] + ], ]; $documents = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1153,6 +1180,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDocument + * * @throws Exception */ public function testGetDocument($data): void @@ -1165,7 +1193,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1227,6 +1255,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase + * * @throws Exception */ public function testUpdateDatabase($database) @@ -1238,7 +1267,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $database['_id'], 'name' => 'New Database Name', - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1253,6 +1282,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testUpdateCollection($data) @@ -1266,7 +1296,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'name' => 'New Collection Name', 'documentSecurity' => false, - ] + ], ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1281,6 +1311,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDocument + * * @throws Exception */ public function testUpdateDocument($data): void @@ -1296,7 +1327,7 @@ class DatabaseServerTest extends Scope 'data' => [ 'name' => 'New Document Name', ], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1341,6 +1372,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDocument + * * @throws Exception */ public function testDeleteDocument($data): void @@ -1353,7 +1385,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ] + ], ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1391,6 +1423,7 @@ class DatabaseServerTest extends Scope /** * @depends testUpdateStringAttribute + * * @throws Exception */ public function testDeleteAttribute($data): void @@ -1403,7 +1436,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'key' => 'name', - ] + ], ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1417,6 +1450,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection + * * @throws Exception */ public function testDeleteCollection($data) @@ -1428,7 +1462,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ] + ], ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1442,6 +1476,7 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase + * * @throws Exception */ public function testDeleteDatabase($database) @@ -1452,7 +1487,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ diff --git a/tests/e2e/Services/GraphQL/FunctionsClientTest.php b/tests/e2e/Services/GraphQL/FunctionsClientTest.php index d5b50250d4..97cbfa9206 100644 --- a/tests/e2e/Services/GraphQL/FunctionsClientTest.php +++ b/tests/e2e/Services/GraphQL/FunctionsClientTest.php @@ -27,7 +27,7 @@ class FunctionsClientTest extends Scope 'name' => 'Test Function', 'runtime' => 'php-8.0', 'execute' => [Role::any()->toString()], - ] + ], ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -36,7 +36,6 @@ class FunctionsClientTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); - $this->assertIsArray($function['body']['data']); $this->assertArrayNotHasKey('errors', $function['body']); @@ -57,7 +56,7 @@ class FunctionsClientTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $functionId, - ] + ], ]; $variables = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -74,15 +73,17 @@ class FunctionsClientTest extends Scope /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testCreateDeployment($function): array { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_DEPLOYMENT); - $code = realpath(__DIR__ . '/../../../resources/functions') . "/php/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions').'/php/code.tar.gz'; $gqlPayload = [ 'operations' => \json_encode([ 'query' => $query, @@ -91,10 +92,10 @@ class FunctionsClientTest extends Scope 'entrypoint' => 'index.php', 'activate' => true, 'code' => null, - ] + ], ]), 'map' => \json_encode([ - 'code' => ["variables.code"] + 'code' => ['variables.code'], ]), 'code' => new CURLFile($code, 'application/gzip', 'code.tar.gz'), ]; @@ -116,9 +117,11 @@ class FunctionsClientTest extends Scope /** * @depends testCreateFunction * @depends testCreateDeployment + * * @param $function * @param $deployment * @return array + * * @throws \Exception */ public function testCreateExecution($function, $deployment): array @@ -129,7 +132,7 @@ class FunctionsClientTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -139,13 +142,16 @@ class FunctionsClientTest extends Scope $this->assertIsArray($execution['body']['data']); $this->assertArrayNotHasKey('errors', $execution['body']); + return $execution['body']['data']['functionsCreateExecution']; } /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testGetExecutions($function): array @@ -156,7 +162,7 @@ class FunctionsClientTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $executions = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -175,9 +181,11 @@ class FunctionsClientTest extends Scope /** * @depends testCreateFunction * @depends testCreateExecution + * * @param $function * @param $execution * @return array + * * @throws \Exception */ public function testGetExecution($function, $execution): array @@ -189,7 +197,7 @@ class FunctionsClientTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'executionId' => $execution['_id'], - ] + ], ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/FunctionsServerTest.php b/tests/e2e/Services/GraphQL/FunctionsServerTest.php index 75aa0d5d04..2771505ba7 100644 --- a/tests/e2e/Services/GraphQL/FunctionsServerTest.php +++ b/tests/e2e/Services/GraphQL/FunctionsServerTest.php @@ -27,7 +27,7 @@ class FunctionsServerTest extends Scope 'name' => 'Test Function', 'runtime' => 'php-8.0', 'execute' => [Role::any()->toString()], - ] + ], ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -55,7 +55,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $functionId, - ] + ], ]; $variables = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -72,15 +72,17 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testCreateDeployment($function): array { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_DEPLOYMENT); - $code = realpath(__DIR__ . '/../../../resources/functions') . "/php/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions').'/php/code.tar.gz'; $gqlPayload = [ 'operations' => \json_encode([ 'query' => $query, @@ -89,10 +91,10 @@ class FunctionsServerTest extends Scope 'entrypoint' => 'index.php', 'activate' => true, 'code' => null, - ] + ], ]), 'map' => \json_encode([ - 'code' => ["variables.code"] + 'code' => ['variables.code'], ]), 'code' => new CURLFile($code, 'application/gzip', 'code.tar.gz'), ]; @@ -113,8 +115,10 @@ class FunctionsServerTest extends Scope /** * * @depends testCreateFunction * @depends testCreateDeployment + * * @param $function * @return array + * * @throws \Exception */ public function testCreateExecution($function): array @@ -125,7 +129,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -142,9 +146,11 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testGetDeployment + * * @param $function * @param $deployment * @return array + * * @throws \Exception */ public function testCreateRetryBuild($function, $deployment): void @@ -157,7 +163,7 @@ class FunctionsServerTest extends Scope 'functionId' => $function['_id'], 'deploymentId' => $deployment['_id'], 'buildId' => $deployment['buildId'], - ] + ], ]; $retryBuild = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -166,7 +172,7 @@ class FunctionsServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($retryBuild['body']['errors']); - $this->assertEquals("Build not failed", $retryBuild['body']['errors'][0]['message']); + $this->assertEquals('Build not failed', $retryBuild['body']['errors'][0]['message']); } public function testGetFunctions(): array @@ -192,8 +198,10 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testGetFunction($function): array @@ -204,7 +212,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -243,8 +251,10 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testGetDeployments($function) @@ -255,7 +265,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $deployments = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -274,8 +284,10 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testCreateDeployment + * * @param $function * @return array + * * @throws \Exception */ public function testGetDeployment($function, $deployment) @@ -287,7 +299,7 @@ class FunctionsServerTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'deploymentId' => $deployment['_id'], - ] + ], ]; $deployment = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -305,8 +317,10 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testGetExecutions($function): array @@ -317,7 +331,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $executions = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -336,9 +350,11 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testCreateExecution + * * @param $function * @param $execution * @return array + * * @throws \Exception */ public function testGetExecution($function, $execution): array @@ -350,7 +366,7 @@ class FunctionsServerTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'executionId' => $execution['_id'], - ] + ], ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -368,8 +384,10 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction + * * @param $function * @return array + * * @throws \Exception */ public function testUpdateFunction($function): array @@ -386,7 +404,7 @@ class FunctionsServerTest extends Scope 'name' => 'John Doe', 'age' => 42, ], - ] + ], ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -405,8 +423,10 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testCreateDeployment + * * @param $function * @param $deployment + * * @throws \Exception */ public function testDeleteDeployment($function, $deployment): void @@ -418,7 +438,7 @@ class FunctionsServerTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'deploymentId' => $deployment['_id'], - ] + ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -433,7 +453,9 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testDeleteDeployment + * * @param $function + * * @throws \Exception */ public function testDeleteFunction($function): void @@ -444,7 +466,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ] + ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/LocalizationTest.php b/tests/e2e/Services/GraphQL/LocalizationTest.php index 38200911c8..2fe76a6f06 100644 --- a/tests/e2e/Services/GraphQL/LocalizationTest.php +++ b/tests/e2e/Services/GraphQL/LocalizationTest.php @@ -18,7 +18,7 @@ class LocalizationTest extends Scope $projectId = $this->getProject()['$id']; $query = \urlencode($this->getQuery(self::$GET_LOCALE)); - $locale = $this->client->call(Client::METHOD_GET, '/graphql?query=' . $query, \array_merge([ + $locale = $this->client->call(Client::METHOD_GET, '/graphql?query='.$query, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders())); diff --git a/tests/e2e/Services/GraphQL/ScopeTest.php b/tests/e2e/Services/GraphQL/ScopeTest.php index a8b5b7cea4..44122887da 100644 --- a/tests/e2e/Services/GraphQL/ScopeTest.php +++ b/tests/e2e/Services/GraphQL/ScopeTest.php @@ -5,7 +5,6 @@ namespace Tests\E2E\Services\GraphQL; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\SideClient; use Tests\E2E\Scopes\SideServer; use Utopia\Database\Helpers\ID; @@ -25,7 +24,7 @@ class ScopeTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -49,7 +48,7 @@ class ScopeTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ] + ], ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', [ diff --git a/tests/e2e/Services/GraphQL/StorageClientTest.php b/tests/e2e/Services/GraphQL/StorageClientTest.php index 9896598c2d..90cfaef7d5 100644 --- a/tests/e2e/Services/GraphQL/StorageClientTest.php +++ b/tests/e2e/Services/GraphQL/StorageClientTest.php @@ -33,7 +33,7 @@ class StorageClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -70,12 +70,12 @@ class StorageClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]), 'map' => \json_encode([ - '0' => ["variables.file"] + '0' => ['variables.file'], ]), - '0' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + '0' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -91,8 +91,10 @@ class StorageClientTest extends Scope /** * @depends testCreateBucket + * * @param $bucket * @return array + * * @throws \Exception */ public function testGetFiles($bucket): array @@ -103,7 +105,7 @@ class StorageClientTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ] + ], ]; $files = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -122,9 +124,11 @@ class StorageClientTest extends Scope /** * @depends testCreateBucket * @depends testCreateFile + * * @param $bucket * @param $file * @return array + * * @throws \Exception */ public function testGetFile($bucket, $file) @@ -136,7 +140,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $bucket['_id'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -152,8 +156,10 @@ class StorageClientTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testGetFilePreview($file) @@ -167,7 +173,7 @@ class StorageClientTest extends Scope 'fileId' => $file['_id'], 'width' => 100, 'height' => 100, - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -182,8 +188,10 @@ class StorageClientTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testGetFileDownload($file) @@ -195,7 +203,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -208,8 +216,10 @@ class StorageClientTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testGetFileView($file): void @@ -221,7 +231,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -234,8 +244,10 @@ class StorageClientTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testUpdateFile($file): array @@ -252,7 +264,7 @@ class StorageClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -270,7 +282,9 @@ class StorageClientTest extends Scope /** * @depends testCreateFile + * * @param $file + * * @throws \Exception */ public function testDeleteFile($file): void @@ -282,7 +296,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/StorageServerTest.php b/tests/e2e/Services/GraphQL/StorageServerTest.php index 7fea895b1c..c4c12e400c 100644 --- a/tests/e2e/Services/GraphQL/StorageServerTest.php +++ b/tests/e2e/Services/GraphQL/StorageServerTest.php @@ -33,7 +33,7 @@ class StorageServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -69,12 +69,12 @@ class StorageServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]), 'map' => \json_encode([ - 'file' => ["variables.file"] + 'file' => ['variables.file'], ]), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -84,6 +84,7 @@ class StorageServerTest extends Scope $this->assertIsArray($file['body']['data']); $this->assertArrayNotHasKey('errors', $file['body']); + return $file['body']['data']['storageCreateFile']; } @@ -110,8 +111,10 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket + * * @param $bucket * @return array + * * @throws \Exception */ public function testGetBucket($bucket): array @@ -122,7 +125,7 @@ class StorageServerTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ] + ], ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -140,8 +143,10 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket + * * @param $bucket * @return array + * * @throws \Exception */ public function testGetFiles($bucket): array @@ -152,7 +157,7 @@ class StorageServerTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ] + ], ]; $files = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -171,9 +176,11 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket * @depends testCreateFile + * * @param $bucket * @param $file * @return array + * * @throws \Exception */ public function testGetFile($bucket, $file) @@ -185,7 +192,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $bucket['_id'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -201,8 +208,10 @@ class StorageServerTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testGetFilePreview($file) @@ -216,7 +225,7 @@ class StorageServerTest extends Scope 'fileId' => $file['_id'], 'width' => 100, 'height' => 100, - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -231,8 +240,10 @@ class StorageServerTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testGetFileDownload($file) @@ -244,7 +255,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -257,8 +268,10 @@ class StorageServerTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testGetFileView($file): void @@ -270,7 +283,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -283,8 +296,10 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket + * * @param $bucket * @return array + * * @throws \Exception */ public function testUpdateBucket($bucket): array @@ -297,7 +312,7 @@ class StorageServerTest extends Scope 'bucketId' => $bucket['_id'], 'name' => 'Actors Updated', 'fileSecurity' => false, - ] + ], ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -315,8 +330,10 @@ class StorageServerTest extends Scope /** * @depends testCreateFile + * * @param $file * @return array + * * @throws \Exception */ public function testUpdateFile($file): array @@ -333,7 +350,7 @@ class StorageServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -351,7 +368,9 @@ class StorageServerTest extends Scope /** * @depends testCreateFile + * * @param $file + * * @throws \Exception */ public function testDeleteFile($file): void @@ -363,7 +382,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ] + ], ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -377,8 +396,10 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket + * * @param $bucket * @return array + * * @throws \Exception */ public function testDeleteBucket($bucket): void @@ -389,7 +410,7 @@ class StorageServerTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ] + ], ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/TeamsServerTest.php b/tests/e2e/Services/GraphQL/TeamsServerTest.php index 33c7847113..a8d8f64ac6 100644 --- a/tests/e2e/Services/GraphQL/TeamsServerTest.php +++ b/tests/e2e/Services/GraphQL/TeamsServerTest.php @@ -125,10 +125,10 @@ class TeamsServerTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'teamId' => $team['_id'], + 'teamId' => $team['_id'], 'prefs' => [ - 'key' => 'value' - ] + 'key' => 'value', + ], ], ]; @@ -156,7 +156,7 @@ class TeamsServerTest extends Scope 'query' => $query, 'variables' => [ 'teamId' => $team['_id'], - ] + ], ]; $prefs = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/UsersTest.php b/tests/e2e/Services/GraphQL/UsersTest.php index 9bd503df0f..e965fc5899 100644 --- a/tests/e2e/Services/GraphQL/UsersTest.php +++ b/tests/e2e/Services/GraphQL/UsersTest.php @@ -7,7 +7,6 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\Database\Helpers\ID; -use Utopia\Database\Query; class UsersTest extends Scope { @@ -27,7 +26,7 @@ class UsersTest extends Scope 'email' => $email, 'password' => 'password', 'name' => 'Project User', - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -56,7 +55,7 @@ class UsersTest extends Scope 'limit(100)', 'offset(0)', ], - ] + ], ]; $users = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -78,7 +77,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -100,7 +99,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -121,7 +120,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -142,7 +141,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -163,7 +162,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -185,7 +184,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'status' => true, - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -208,7 +207,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'emailVerification' => true, - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -230,7 +229,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'phoneVerification' => true, - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -253,7 +252,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'name' => 'Updated Name', - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -275,7 +274,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - 'email' => 'newemail@appwrite.io' + 'email' => 'newemail@appwrite.io', ], ]; @@ -298,7 +297,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - 'password' => 'newpassword' + 'password' => 'newpassword', ], ]; @@ -320,7 +319,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - 'number' => '+123456789' + 'number' => '+123456789', ], ]; @@ -344,8 +343,8 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'prefs' => [ - 'key' => 'value' - ] + 'key' => 'value', + ], ], ]; @@ -368,7 +367,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -392,7 +391,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'sessionId' => $this->getUser()['sessionId'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -415,7 +414,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ] + ], ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/Health/HealthBase.php b/tests/e2e/Services/Health/HealthBase.php index cbd0f97668..545cbc893f 100644 --- a/tests/e2e/Services/Health/HealthBase.php +++ b/tests/e2e/Services/Health/HealthBase.php @@ -2,8 +2,6 @@ namespace Tests\E2E\Services\Health; -use Tests\E2E\Client; - trait HealthBase { } diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 96c9bde5c7..23b9833c96 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -3,9 +3,8 @@ namespace Tests\E2E\Services\Health; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; -use Tests\E2E\Scopes\SideClient; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; class HealthCustomServerTest extends Scope diff --git a/tests/e2e/Services/Locale/LocaleBase.php b/tests/e2e/Services/Locale/LocaleBase.php index 17b5c66d67..38d6a61fd5 100644 --- a/tests/e2e/Services/Locale/LocaleBase.php +++ b/tests/e2e/Services/Locale/LocaleBase.php @@ -100,7 +100,6 @@ trait LocaleBase $this->assertEquals($response['body']['countries'][0]['name'], 'Alemania'); $this->assertEquals($response['body']['countries'][0]['code'], 'DE'); - /** * Test for FAILURE */ @@ -162,7 +161,6 @@ trait LocaleBase $this->assertEquals($response['body']['continents'][0]['code'], 'NA'); $this->assertEquals($response['body']['continents'][0]['name'], 'América del Norte'); - /** * Test for FAILURE */ @@ -227,9 +225,9 @@ trait LocaleBase /** * Test for SUCCESS */ - $languages = require('app/config/locale/codes.php'); - $defaultCountries = require('app/config/locale/countries.php'); - $defaultContinents = require('app/config/locale/continents.php'); + $languages = require 'app/config/locale/codes.php'; + $defaultCountries = require 'app/config/locale/countries.php'; + $defaultContinents = require 'app/config/locale/continents.php'; foreach ($languages as $lang) { $response = $this->client->call(Client::METHOD_GET, '/locale/countries', [ @@ -238,12 +236,12 @@ trait LocaleBase 'x-appwrite-locale' => $lang['code'], ]); - if (!\is_array($response['body']['countries'])) { - throw new Exception('Failed to iterate locale: ' . $lang); + if (! \is_array($response['body']['countries'])) { + throw new Exception('Failed to iterate locale: '.$lang); } foreach ($response['body']['countries'] as $i => $code) { - $this->assertContains($code['code'], $defaultCountries, $code['code'] . ' country should be removed from ' . $lang['code']); + $this->assertContains($code['code'], $defaultCountries, $code['code'].' country should be removed from '.$lang['code']); } $this->assertEquals($response['headers']['status-code'], 200); @@ -256,7 +254,7 @@ trait LocaleBase ]); foreach ($response['body']['continents'] as $i => $code) { - $this->assertContains($code['code'], $defaultContinents, $code['code'] . ' continent should be removed from ' . $lang['code']); + $this->assertContains($code['code'], $defaultContinents, $code['code'].' continent should be removed from '.$lang['code']); } $this->assertEquals($response['headers']['status-code'], 200); diff --git a/tests/e2e/Services/Locale/LocaleConsoleClientTest.php b/tests/e2e/Services/Locale/LocaleConsoleClientTest.php index 29b3150fed..c72e554df7 100644 --- a/tests/e2e/Services/Locale/LocaleConsoleClientTest.php +++ b/tests/e2e/Services/Locale/LocaleConsoleClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Locale; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; class LocaleConsoleClientTest extends Scope diff --git a/tests/e2e/Services/Locale/LocaleCustomClientTest.php b/tests/e2e/Services/Locale/LocaleCustomClientTest.php index b28584280e..6d6108dec1 100644 --- a/tests/e2e/Services/Locale/LocaleCustomClientTest.php +++ b/tests/e2e/Services/Locale/LocaleCustomClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Locale; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; class LocaleCustomClientTest extends Scope diff --git a/tests/e2e/Services/Locale/LocaleCustomServerTest.php b/tests/e2e/Services/Locale/LocaleCustomServerTest.php index 62d4e76802..1513f9b342 100644 --- a/tests/e2e/Services/Locale/LocaleCustomServerTest.php +++ b/tests/e2e/Services/Locale/LocaleCustomServerTest.php @@ -2,7 +2,6 @@ namespace Tests\E2E\Services\Locale; -use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 9bc9f93caf..8f477173eb 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -65,7 +65,7 @@ class MessagingServerTest extends Scope $providers = []; foreach (\array_keys($providersParams) as $key) { - $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, [ + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/'.$key, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -132,7 +132,7 @@ class MessagingServerTest extends Scope ], ]; foreach (\array_keys($providersParams) as $index => $key) { - $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $providers[$index]['$id'] . '/' . $key, [ + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/'.$providers[$index]['$id'].'/'.$key, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -164,7 +164,7 @@ class MessagingServerTest extends Scope */ public function testGetProvider(array $providers) { - $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $providers[0]['$id'], [ + $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/'.$providers[0]['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -179,7 +179,7 @@ class MessagingServerTest extends Scope public function testDeleteProvider(array $providers) { foreach ($providers as $provider) { - $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/' . $provider['$id'], [ + $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/'.$provider['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -187,5 +187,4 @@ class MessagingServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } } - } diff --git a/tests/e2e/Services/Projects/ProjectsBase.php b/tests/e2e/Services/Projects/ProjectsBase.php index a9ccd73900..53d9626252 100644 --- a/tests/e2e/Services/Projects/ProjectsBase.php +++ b/tests/e2e/Services/Projects/ProjectsBase.php @@ -2,8 +2,6 @@ namespace Tests\E2E\Services\Projects; -use Tests\E2E\Client; - trait ProjectsBase { } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 31c8c72a14..5006ab224a 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -4,10 +4,10 @@ namespace Tests\E2E\Services\Projects; use Appwrite\Auth\Auth; use Appwrite\Extend\Exception; -use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\ProjectConsole; -use Tests\E2E\Scopes\SideClient; use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectConsole; +use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\SideClient; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; @@ -84,7 +84,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => '', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => 'default', ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -95,14 +95,14 @@ class ProjectsConsoleClientTest extends Scope ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Project Test', - 'region' => 'default' + 'region' => 'default', ]); $this->assertEquals(400, $response['headers']['status-code']); return [ 'projectId' => $projectId, - 'teamId' => $team['body']['$id'] + 'teamId' => $team['body']['$id'], ]; } @@ -124,7 +124,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => $projectId, 'name' => 'Project Duplicate', 'teamId' => $teamId, - 'region' => 'default' + 'region' => 'default', ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -187,7 +187,7 @@ class ProjectsConsoleClientTest extends Scope $projectId = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $projectId . '/team', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$projectId.'/team', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -211,7 +211,6 @@ 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'], @@ -229,7 +228,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => $id + 'search' => $id, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -242,7 +241,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => 'Project Test' + 'search' => 'Project Test', ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -273,7 +272,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test 2', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => 'default', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -288,7 +287,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("teamId", "' . $team['body']['$id'] . '")' ], + 'queries' => ['equal("teamId", "'.$team['body']['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -300,7 +299,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ], + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -312,7 +311,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(3)' ], + 'queries' => ['offset(3)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -324,7 +323,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("name", "Project Test 2")' ], + 'queries' => ['equal("name", "Project Test 2")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -336,7 +335,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'orderDesc("")' ], + 'queries' => ['orderDesc("")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -360,7 +359,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("' . $response['body']['projects'][0]['$id'] . '")' ], + 'queries' => ['cursorAfter("'.$response['body']['projects'][0]['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -372,7 +371,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorBefore("' . $response['body']['projects'][0]['$id'] . '")' ], + 'queries' => ['cursorBefore("'.$response['body']['projects'][0]['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -387,7 +386,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("unknown")' ], + 'queries' => ['cursorAfter("unknown")'], ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -405,7 +404,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -418,7 +417,6 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/empty', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -467,7 +465,6 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/empty', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -495,7 +492,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -515,7 +512,6 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -536,7 +532,7 @@ class ProjectsConsoleClientTest extends Scope public function testUpdateProjectSMTP($data): array { $id = $data['projectId']; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/smtp', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/smtp', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -558,7 +554,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['smtpSecure']); /** Test Reading Project */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -573,7 +569,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['smtpSecure']); /** Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/smtp', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/smtp', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -584,6 +580,7 @@ class ProjectsConsoleClientTest extends Scope 'username' => 'user', 'password' => 'password', ]); + return $data; } @@ -595,7 +592,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId']; /** Get Default Email Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/email/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/email/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -609,7 +606,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertMatchesRegularExpression('//', $response['body']['message']); /** Update Email template */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/templates/email/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/templates/email/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -628,7 +625,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('Please verify your email {{url}}', $response['body']['message']); /** Get Updated Email Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/email/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/email/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -642,7 +639,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('Please verify your email {{url}}', $response['body']['message']); /** Get Default SMS Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/sms/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/sms/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -653,7 +650,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('{{token}}', $response['body']['message']); /** Update SMS template */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/templates/sms/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/templates/sms/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -666,7 +663,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('Please verify your email {{token}}', $response['body']['message']); /** Get Updated SMS Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/sms/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/sms/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -685,7 +682,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId']; // Check defaults - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); @@ -696,8 +693,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/duration', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/duration', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -720,7 +716,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'userId' => 'unique()', - 'email' => 'test' . rand(0, 9999) . '@example.com', + 'email' => 'test'.rand(0, 9999).'@example.com', 'password' => 'password', 'name' => 'Test User', ]); @@ -777,7 +773,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(401, $response['headers']['status-code']); // Return project back to normal - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/duration', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/duration', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -788,7 +784,7 @@ class ProjectsConsoleClientTest extends Scope $projectId = $response['body']['$id']; // Check project is back to normal - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); @@ -805,27 +801,26 @@ class ProjectsConsoleClientTest extends Scope public function testUpdateProjectOAuth($data): array { $id = $data['projectId'] ?? ''; - $providers = require('app/config/authProviders.php'); + $providers = require 'app/config/authProviders.php'; /** * Test for SUCCESS */ - foreach ($providers as $key => $provider) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/oauth2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'provider' => $key, - 'appId' => 'AppId-' . ucfirst($key), - 'secret' => 'Secret-' . ucfirst($key), + 'appId' => 'AppId-'.ucfirst($key), + 'secret' => 'Secret-'.ucfirst($key), ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); } - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -838,8 +833,8 @@ class ProjectsConsoleClientTest extends Scope $asserted = false; foreach ($response['body']['providers'] as $responseProvider) { if ($responseProvider['key'] === $key) { - $this->assertEquals('AppId-' . ucfirst($key), $responseProvider['appId']); - $this->assertEquals('Secret-' . ucfirst($key), $responseProvider['secret']); + $this->assertEquals('AppId-'.ucfirst($key), $responseProvider['appId']); + $this->assertEquals('Secret-'.ucfirst($key), $responseProvider['secret']); $this->assertFalse($responseProvider['enabled']); $asserted = true; break; @@ -852,12 +847,12 @@ class ProjectsConsoleClientTest extends Scope // Enable providers $i = 0; foreach ($providers as $key => $provider) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/oauth2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'provider' => $key, - 'enabled' => $i === 0 ? false : true // On first provider, test enabled=false + 'enabled' => $i === 0 ? false : true, // On first provider, test enabled=false ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -866,7 +861,7 @@ class ProjectsConsoleClientTest extends Scope $i++; } - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -895,8 +890,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/oauth2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -916,9 +910,9 @@ class ProjectsConsoleClientTest extends Scope public function testUpdateProjectAuthStatus($data): array { $id = $data['projectId'] ?? ''; - $auth = require('app/config/auth.php'); + $auth = require 'app/config/auth.php'; - $originalEmail = uniqid() . 'user@localhost.test'; + $originalEmail = uniqid().'user@localhost.test'; $originalPassword = 'password'; $originalName = 'User Name'; @@ -942,13 +936,13 @@ class ProjectsConsoleClientTest extends Scope 'password' => $originalPassword, ]); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $id]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$id]; /** * Test for SUCCESS */ foreach ($auth as $index => $method) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/' . $index, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/'.$index, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -958,17 +952,17 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['auth' . ucfirst($method['key'])]); + $this->assertEquals(false, $response['body']['auth'.ucfirst($method['key'])]); } - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -991,25 +985,25 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_' . $id . '=' . $session, + 'cookie' => 'a_session_'.$id.'='.$session, ]), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal' + 'name' => 'Arsenal', ]); $this->assertEquals(201, $response['headers']['status-code']); $teamUid = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_' . $id . '=' . $session, + 'cookie' => 'a_session_'.$id.'='.$session, ]), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals($response['headers']['status-code'], 501); @@ -1017,7 +1011,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/account/jwt', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_' . $id . '=' . $session, + 'cookie' => 'a_session_'.$id.'='.$session, ])); $this->assertEquals($response['headers']['status-code'], 501); @@ -1044,7 +1038,7 @@ class ProjectsConsoleClientTest extends Scope // Cleanup foreach ($auth as $index => $method) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/' . $index, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/'.$index, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1065,7 +1059,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/limit', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/limit', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1075,7 +1069,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -1093,7 +1087,7 @@ class ProjectsConsoleClientTest extends Scope 'name' => $name, ]); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'origin' => 'http://localhost', @@ -1111,7 +1105,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/limit', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/limit', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1121,7 +1115,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'origin' => 'http://localhost', @@ -1149,7 +1143,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for failure */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/max-sessions', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/max-sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1161,7 +1155,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/max-sessions', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/max-sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1172,7 +1166,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertEquals(1, $response['body']['authSessionsLimit']); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -1204,7 +1198,6 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, ]); - $this->assertEquals(201, $response['headers']['status-code']); $sessionId1 = $response['body']['$id']; @@ -1220,7 +1213,6 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, ]); - $this->assertEquals(201, $response['headers']['status-code']); $sessionCookie = $response['headers']['set-cookie']; $sessionId2 = $response['body']['$id']; @@ -1247,7 +1239,7 @@ class ProjectsConsoleClientTest extends Scope /** * Reset Limit */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/max-sessions', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/max-sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1257,7 +1249,6 @@ class ProjectsConsoleClientTest extends Scope return $data; } - /** * @depends testUpdateProjectAuthLimit */ @@ -1268,7 +1259,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for Failure */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1277,11 +1268,10 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - /** * Test for Success */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1291,8 +1281,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(1, $response['body']['authPasswordHistory']); - - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -1324,13 +1313,13 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, ]); $this->assertEquals(201, $session['headers']['status-code']); - $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $id]; + $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$id]; $response = $this->client->call(Client::METHOD_PATCH, '/account/password', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_' . $id . '=' . $session, + 'cookie' => 'a_session_'.$id.'='.$session, ]), [ 'oldPassword' => $password, 'password' => $password, @@ -1344,17 +1333,16 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]); - $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $userId . '/password', $headers, [ + $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$userId.'/password', $headers, [ 'password' => $password, ]); $this->assertEquals(400, $response['headers']['status-code']); - - /** + /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1363,6 +1351,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(0, $response['body']['authPasswordHistory']); + return $data; } @@ -1389,7 +1378,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]), [ 'userId' => ID::unique(), - 'email' => uniqid() . 'user@localhost.test', + 'email' => uniqid().'user@localhost.test', 'password' => $password, 'name' => $name, ]); @@ -1405,7 +1394,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-mode' => 'admin', ]), [ 'userId' => ID::unique(), - 'email' => uniqid() . 'user@localhost.test', + 'email' => uniqid().'user@localhost.test', 'password' => 'password', 'name' => 'Cristiano Ronaldo', ]); @@ -1414,7 +1403,7 @@ class ProjectsConsoleClientTest extends Scope /** * Enable Disctionary */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-dictionary', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-dictionary', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1433,7 +1422,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]), [ 'userId' => ID::unique(), - 'email' => uniqid() . 'user@localhost.test', + 'email' => uniqid().'user@localhost.test', 'password' => $password, 'name' => $name, ]); @@ -1449,7 +1438,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-mode' => 'admin', ]), [ 'userId' => ID::unique(), - 'email' => uniqid() . 'user@localhost.test', + 'email' => uniqid().'user@localhost.test', 'password' => 'password', 'name' => 'Cristiano Ronaldo', ]); @@ -1461,17 +1450,16 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]); - $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $userId . '/password', $headers, [ + $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$userId.'/password', $headers, [ 'password' => $password, ]); $this->assertEquals(400, $response['headers']['status-code']); - - /** + /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1484,7 +1472,7 @@ class ProjectsConsoleClientTest extends Scope /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-dictionary', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-dictionary', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1507,7 +1495,7 @@ class ProjectsConsoleClientTest extends Scope /** * Enable Disallowing of Personal Data */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/personal-data', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/personal-data', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1520,7 +1508,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for failure */ - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'username'; $userId = ID::unique(); @@ -1533,7 +1521,7 @@ class ProjectsConsoleClientTest extends Scope 'email' => $email, 'password' => $email, 'name' => $name, - 'userId' => $userId + 'userId' => $userId, ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -1548,7 +1536,7 @@ class ProjectsConsoleClientTest extends Scope 'email' => $email, 'password' => $name, 'name' => $name, - 'userId' => $userId + 'userId' => $userId, ]); $phone = '+123456789'; @@ -1561,7 +1549,7 @@ class ProjectsConsoleClientTest extends Scope 'password' => $phone, 'name' => $name, 'userId' => $userId, - 'phone' => $phone + 'phone' => $phone, ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -1569,7 +1557,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(Exception::USER_PASSWORD_PERSONAL_DATA, $response['body']['type']); /** Test for success */ - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'username'; $userId = ID::unique(); @@ -1581,12 +1569,12 @@ class ProjectsConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'userId' => $userId + 'userId' => $userId, ]); $this->assertEquals(201, $response['headers']['status-code']); - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $userId = ID::unique(); $response = $this->client->call(Client::METHOD_POST, '/users', array_merge($this->getHeaders(), [ 'content-type' => 'application/json', @@ -1597,16 +1585,15 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, 'name' => $name, 'userId' => $userId, - 'phone' => $phone + 'phone' => $phone, ]); $this->assertEquals(201, $response['headers']['status-code']); - /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/personal-data', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/personal-data', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1617,13 +1604,12 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(false, $response['body']['authPersonalDataCheck']); } - public function testUpdateProjectServiceStatusAdmin(): array { $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'teamId' => ID::unique(), 'name' => 'Project Test', @@ -1634,34 +1620,34 @@ class ProjectsConsoleClientTest extends Scope $project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'projectId' => ID::unique(), 'name' => 'Project Test', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => 'default', ]); $this->assertEquals(201, $project['headers']['status-code']); $this->assertNotEmpty($project['body']['$id']); $id = $project['body']['$id']; - $services = require('app/config/services.php'); + $services = require 'app/config/services.php'; /** * Test for Disabled */ foreach ($services as $service) { - if (!$service['optional']) { + if (! $service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'service' => $key, 'status' => false, @@ -1670,40 +1656,39 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); + $this->assertEquals(false, $response['body']['serviceStatusFor'.ucfirst($key)]); } /** * Admin request must succeed */ - $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', // 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $id, - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], - 'x-appwrite-mode' => 'admin' + 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'x-appwrite-mode' => 'admin', ])); $this->assertEquals(200, $response['headers']['status-code']); foreach ($services as $service) { - if (!$service['optional']) { + if (! $service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1720,22 +1705,22 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId']; - $services = require('app/config/services.php'); + $services = require 'app/config/services.php'; /** * Test for Disabled */ foreach ($services as $service) { - if (!$service['optional']) { + if (! $service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'service' => $key, 'status' => false, @@ -1744,15 +1729,15 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); + $this->assertEquals(false, $response['body']['serviceStatusFor'.ucfirst($key)]); } /** @@ -1771,7 +1756,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal' + 'name' => 'Arsenal', ]); $this->assertEquals(503, $response['headers']['status-code']); @@ -1779,7 +1764,7 @@ class ProjectsConsoleClientTest extends Scope // Cleanup foreach ($services as $service) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1794,22 +1779,22 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId']; - $services = require('app/config/services.php'); + $services = require 'app/config/services.php'; /** * Test for Disabled */ foreach ($services as $service) { - if (!$service['optional']) { + if (! $service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'service' => $key, 'status' => false, @@ -1818,22 +1803,22 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); + $this->assertEquals(false, $response['body']['serviceStatusFor'.ucfirst($key)]); } // Create API Key - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), [ 'name' => 'Key Test', 'scopes' => ['functions.read', 'teams.write'], @@ -1851,7 +1836,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $id, 'x-appwrite-key' => $keySecret, - 'x-sdk-name' => 'python' + 'x-sdk-name' => 'python', ])); $this->assertEquals(200, $response['headers']['status-code']); @@ -1860,19 +1845,19 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $id, 'x-appwrite-key' => $keySecret, - 'x-sdk-name' => 'php' + 'x-sdk-name' => 'php', ]), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal' + 'name' => 'Arsenal', ]); $this->assertEquals(201, $response['headers']['status-code']); /** Check that the API key has been updated */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -1885,16 +1870,16 @@ class ProjectsConsoleClientTest extends Scope // Cleanup - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ]), []); $this->assertEquals(204, $response['headers']['status-code']); foreach ($services as $service) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1911,7 +1896,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1938,7 +1923,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1952,7 +1937,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1973,7 +1958,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -1996,7 +1981,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $webhookId = $data['webhookId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2014,7 +1999,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2032,7 +2017,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $webhookId = $data['webhookId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2056,7 +2041,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['httpUser']); $this->assertEquals('', $response['body']['httpPass']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2078,7 +2063,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2090,7 +2075,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2102,7 +2087,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2125,7 +2110,7 @@ class ProjectsConsoleClientTest extends Scope $webhookId = $data['webhookId'] ?? ''; $signatureKey = $data['signatureKey'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/webhooks/' . $webhookId . '/signature', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/webhooks/'.$webhookId.'/signature', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2143,7 +2128,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $webhookId = $data['webhookId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2151,7 +2136,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2161,7 +2146,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/webhooks/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2180,7 +2165,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2201,13 +2186,13 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, [ 'keyId' => $response['body']['$id'], - 'secret' => $response['body']['secret'] + 'secret' => $response['body']['secret'], ]); /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2220,7 +2205,6 @@ class ProjectsConsoleClientTest extends Scope return $data; } - /** * @depends testCreateProjectKey */ @@ -2228,12 +2212,11 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); - $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(1, $response['body']['total']); @@ -2244,7 +2227,6 @@ class ProjectsConsoleClientTest extends Scope return $data; } - /** * @depends testCreateProjectKey */ @@ -2253,10 +2235,10 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $keyId = $data['keyId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $keyId + 'x-appwrite-key' => $keyId, ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2275,7 +2257,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2295,7 +2277,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2307,7 +2289,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/health', [ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'x-appwrite-key' => $response['body']['secret'] + 'x-appwrite-key' => $response['body']['secret'], ], []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2315,7 +2297,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2327,7 +2309,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/health', [ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'x-appwrite-key' => $response['body']['secret'] + 'x-appwrite-key' => $response['body']['secret'], ], []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2335,7 +2317,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2347,13 +2329,12 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/health', [ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'x-appwrite-key' => $response['body']['secret'] + 'x-appwrite-key' => $response['body']['secret'], ], []); $this->assertEquals(401, $response['headers']['status-code']); } - /** * @depends testCreateProjectKey */ @@ -2362,7 +2343,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $keyId = $data['keyId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2384,7 +2365,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertArrayHasKey('accessedAt', $response['body']); $this->assertEmpty($response['body']['accessedAt']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2405,7 +2386,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2426,7 +2407,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $keyId = $data['keyId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2434,7 +2415,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2444,7 +2425,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/keys/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2463,7 +2444,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2482,7 +2463,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformWebId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2501,7 +2482,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformFultteriOSId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2520,7 +2501,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformFultterAndroidId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2539,7 +2520,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformFultterWebId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2558,7 +2539,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformAppleIosId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2577,7 +2558,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformAppleMacOsId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2596,7 +2577,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformAppleWatchOsId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2618,7 +2599,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2641,7 +2622,7 @@ class ProjectsConsoleClientTest extends Scope sleep(1); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2665,7 +2646,7 @@ class ProjectsConsoleClientTest extends Scope $platformWebId = $data['platformWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2681,7 +2662,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultteriOSId = $data['platformFultteriOSId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2697,7 +2678,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterAndroidId = $data['platformFultterAndroidId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2713,7 +2694,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterWebId = $data['platformFultterWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2729,7 +2710,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleIosId = $data['platformAppleIosId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2745,7 +2726,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleMacOsId = $data['platformAppleMacOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2761,7 +2742,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleWatchOsId = $data['platformAppleWatchOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2777,7 +2758,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleTvOsId = $data['platformAppleTvOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2794,7 +2775,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2813,7 +2794,7 @@ class ProjectsConsoleClientTest extends Scope $platformWebId = $data['platformWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2832,7 +2813,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultteriOSId = $data['platformFultteriOSId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2851,7 +2832,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterAndroidId = $data['platformFultterAndroidId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2870,7 +2851,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterWebId = $data['platformFultterWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2889,7 +2870,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleIosId = $data['platformAppleIosId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2908,7 +2889,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleMacOsId = $data['platformAppleMacOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2927,7 +2908,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleWatchOsId = $data['platformAppleWatchOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2946,7 +2927,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleTvOsId = $data['platformAppleTvOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2966,7 +2947,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/error', array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2988,7 +2969,7 @@ class ProjectsConsoleClientTest extends Scope $platformWebId = $data['platformWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2996,7 +2977,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3005,7 +2986,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultteriOSId = $data['platformFultteriOSId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3013,7 +2994,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3022,7 +3003,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterAndroidId = $data['platformFultterAndroidId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3030,7 +3011,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3039,7 +3020,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterWebId = $data['platformFultterWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3047,7 +3028,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3056,7 +3037,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleIosId = $data['platformAppleIosId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3064,7 +3045,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3073,7 +3054,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleMacOsId = $data['platformAppleMacOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3081,7 +3062,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3090,7 +3071,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleWatchOsId = $data['platformAppleWatchOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3098,7 +3079,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3107,7 +3088,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleTvOsId = $data['platformAppleTvOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3115,7 +3096,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3125,7 +3106,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/webhooks/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3144,7 +3125,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/domains', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/domains', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3164,7 +3145,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3173,13 +3154,13 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'type' => 'web', 'name' => 'Too Long Hostname', - 'hostname' => \str_repeat("bestdomain", 25) . '.com' // 250 + 4 chars total (exactly above limit) + 'hostname' => \str_repeat('bestdomain', 25).'.com', // 250 + 4 chars total (exactly above limit) ]); return $data; @@ -3192,7 +3173,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3215,7 +3196,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $domainId = $data['domainId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains/' . $domainId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains/'.$domainId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3232,7 +3213,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3250,7 +3231,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $domainId = $data['domainId'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/domains/' . $domainId . '/verification', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/domains/'.$domainId.'/verification', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3272,7 +3253,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $domainId = $data['domainId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/domains/' . $domainId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/domains/'.$domainId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3280,7 +3261,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains/' . $domainId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains/'.$domainId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3290,7 +3271,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/domains/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/domains/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3326,7 +3307,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Amazing Project', 'teamId' => $teamId, - 'region' => 'default' + 'region' => 'default', ]); $this->assertEquals(201, $project['headers']['status-code']); @@ -3337,14 +3318,14 @@ class ProjectsConsoleClientTest extends Scope $projectId = $project['body']['$id']; // Ensure I can get both team and project - $team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $team['headers']['status-code']); - $project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([ + $project = $this->client->call(Client::METHOD_GET, '/projects/'.$projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3352,7 +3333,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $project['headers']['status-code']); // Delete Project - $project = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId, array_merge([ + $project = $this->client->call(Client::METHOD_DELETE, '/projects/'.$projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3360,14 +3341,14 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $project['headers']['status-code']); // Ensure I can get team but not a project - $team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $team['headers']['status-code']); - $project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([ + $project = $this->client->call(Client::METHOD_GET, '/projects/'.$projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php index 9dfd48ce50..25140309af 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php @@ -2,10 +2,9 @@ namespace Tests\E2E\Services\Projects; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; -use Tests\E2E\Client; class ProjectsCustomClientTest extends Scope { diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index 1c5b48f146..436d1df611 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -5,7 +5,6 @@ namespace Tests\E2E\Services\Projects; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use Tests\E2E\Client; class ProjectsCustomServerTest extends Scope { diff --git a/tests/e2e/Services/Realtime/RealtimeBase.php b/tests/e2e/Services/Realtime/RealtimeBase.php index 62bb7f5d3b..baf27e78ea 100644 --- a/tests/e2e/Services/Realtime/RealtimeBase.php +++ b/tests/e2e/Services/Realtime/RealtimeBase.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Realtime; -use WebSocket\ConnectionException; use WebSocket\Client as WebSocketClient; +use WebSocket\ConnectionException; trait RealtimeBase { @@ -14,15 +14,15 @@ trait RealtimeBase } $headers = array_merge([ - 'Origin' => 'appwrite.test' + 'Origin' => 'appwrite.test', ], $headers); $query = [ 'project' => $projectId, - 'channels' => $channels + 'channels' => $channels, ]; - return new WebSocketClient('ws://appwrite-traefik/v1/realtime?' . http_build_query($query), [ + return new WebSocketClient('ws://appwrite-traefik/v1/realtime?'.http_build_query($query), [ 'headers' => $headers, 'timeout' => 30, ]); @@ -57,8 +57,8 @@ trait RealtimeBase { $client = new WebSocketClient('ws://appwrite-traefik/v1/realtime?project=123', [ 'headers' => [ - 'Origin' => 'appwrite.test' - ] + 'Origin' => 'appwrite.test', + ], ]); $payload = json_decode($client->receive(), true); diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 3ef258885c..363da4d611 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -4,8 +4,8 @@ namespace Tests\E2E\Services\Realtime; use CURLFile; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; use Tests\E2E\Services\Functions\FunctionsBase; use Utopia\Database\Helpers\ID; @@ -29,7 +29,7 @@ class RealtimeConsoleClientTest extends Scope * Test for SUCCESS */ $client = $this->getWebsocket(['account'], [ - 'origin' => 'http://localhost' + 'origin' => 'http://localhost', ]); $response = json_decode($client->receive(), true); @@ -43,8 +43,8 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => $session - ] + 'session' => $session, + ], ])); $response = json_decode($client->receive(), true); @@ -64,8 +64,8 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => 'invalid_session' - ] + 'session' => 'invalid_session', + ], ])); $response = json_decode($client->receive(), true); @@ -79,7 +79,7 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', - 'data' => [] + 'data' => [], ])); $response = json_decode($client->receive(), true); @@ -94,8 +94,8 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'unknown', 'data' => [ - 'session' => 'invalid_session' - ] + 'session' => 'invalid_session', + ], ])); $response = json_decode($client->receive(), true); @@ -120,7 +120,6 @@ class RealtimeConsoleClientTest extends Scope $this->assertEquals(1003, $response['data']['code']); $this->assertEquals('Message format is not valid.', $response['data']['message']); - $client->close(); } @@ -131,7 +130,7 @@ class RealtimeConsoleClientTest extends Scope $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -159,7 +158,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Attributes */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -175,7 +174,7 @@ class RealtimeConsoleClientTest extends Scope $actorsId = $actors['body']['$id']; - $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ + $name = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -207,7 +206,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('processing', $response['data']['payload']['status']); @@ -227,7 +226,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('available', $response['data']['payload']['status']); @@ -248,7 +247,7 @@ class RealtimeConsoleClientTest extends Scope $databaseId = $data['databaseId']; $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -264,7 +263,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Indexes */ - $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -330,7 +329,7 @@ class RealtimeConsoleClientTest extends Scope $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -346,7 +345,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Delete Index */ - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/indexes/key_name', array_merge([ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/indexes/key_name', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -386,7 +385,7 @@ class RealtimeConsoleClientTest extends Scope $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -402,7 +401,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Delete Attribute */ - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/attributes/name', array_merge([ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/attributes/name', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -443,19 +442,18 @@ class RealtimeConsoleClientTest extends Scope 'users.*.delete', ], 'schedule' => '0 0 1 1 *', - 'timeout' => 10 + 'timeout' => 10, ]); $functionId = $response1['body']['$id'] ?? ''; $this->assertEquals(201, $response1['headers']['status-code']); - $projectId = 'console'; $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'cookie' => 'a_session_console='.$this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -471,18 +469,17 @@ class RealtimeConsoleClientTest extends Scope /** * Test Create Deployment */ - $folder = 'php'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 4f880338a4..456bb7d333 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -4,8 +4,8 @@ namespace Tests\E2E\Services\Realtime; use CURLFile; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\CLI\Console; use Utopia\Database\Helpers\ID; @@ -25,9 +25,9 @@ class RealtimeCustomClientTest extends Scope $userId = $user['$id'] ?? ''; $session = $user['session'] ?? ''; - $headers = [ + $headers = [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]; $client = $this->getWebsocket(['documents'], $headers); @@ -54,7 +54,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']['user']); $this->assertCount(2, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -70,7 +70,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(3, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -96,7 +96,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']['user']); $this->assertCount(10, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains('files', $response['data']['channels']); $this->assertContains('files.1', $response['data']['channels']); $this->assertContains('collections', $response['data']['channels']); @@ -120,7 +120,7 @@ class RealtimeCustomClientTest extends Scope * Test for SUCCESS */ $client = $this->getWebsocket(['account'], [ - 'origin' => 'http://localhost' + 'origin' => 'http://localhost', ]); $response = json_decode($client->receive(), true); @@ -134,8 +134,8 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => $session - ] + 'session' => $session, + ], ])); $response = json_decode($client->receive(), true); @@ -155,8 +155,8 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => 'invalid_session' - ] + 'session' => 'invalid_session', + ], ])); $response = json_decode($client->receive(), true); @@ -170,7 +170,7 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', - 'data' => [] + 'data' => [], ])); $response = json_decode($client->receive(), true); @@ -185,8 +185,8 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'unknown', 'data' => [ - 'session' => 'invalid_session' - ] + 'session' => 'invalid_session', + ], ])); $response = json_decode($client->receive(), true); @@ -211,7 +211,6 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals(1003, $response['data']['code']); $this->assertEquals('Message format is not valid.', $response['data']['message']); - $client->close(); } @@ -242,7 +241,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['account'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -252,22 +251,22 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertNotEmpty($response['data']['user']); $this->assertEquals($userId, $response['data']['user']['$id']); /** * Test Account Name Event */ - $name = "Torsten Dittmann"; + $name = 'Torsten Dittmann'; $this->client->call(Client::METHOD_PATCH, '/account/name', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $session, + 'cookie' => 'a_session_'.$projectId.'='.$session, ]), [ - 'name' => $name + 'name' => $name, ]); $response = json_decode($client->receive(), true); @@ -279,18 +278,17 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.name", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains("users.*.update.name", $response['data']['events']); - $this->assertContains("users.*.update", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.update.name', $response['data']['events']); + $this->assertContains('users.*.update', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($name, $response['data']['payload']['name']); - /** * Test Account Password Event */ @@ -298,7 +296,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $session, + 'cookie' => 'a_session_'.$projectId.'='.$session, ]), [ 'password' => 'new-password', 'oldPassword' => 'password', @@ -313,13 +311,13 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.password", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains("users.*.update.password", $response['data']['events']); - $this->assertContains("users.*.update", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.update.password', $response['data']['events']); + $this->assertContains('users.*.update', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($name, $response['data']['payload']['name']); @@ -331,7 +329,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $session, + 'cookie' => 'a_session_'.$projectId.'='.$session, ]), [ 'email' => 'torsten@appwrite.io', 'password' => 'new-password', @@ -346,13 +344,13 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.email", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains("users.*.update.email", $response['data']['events']); - $this->assertContains("users.*.update", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.update.email', $response['data']['events']); + $this->assertContains('users.*.update', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('torsten@appwrite.io', $response['data']['payload']['email']); @@ -363,7 +361,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $session, + 'cookie' => 'a_session_'.$projectId.'='.$session, ]), [ 'url' => 'http://localhost/verification', ]); @@ -377,7 +375,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.verification.{$verificationId}.create", $response['data']['events']); $this->assertContains("users.{$userId}.verification.{$verificationId}", $response['data']['events']); $this->assertContains("users.{$userId}.verification.*.create", $response['data']['events']); @@ -385,9 +383,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}.create", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}", $response['data']['events']); - $this->assertContains("users.*.verification.*.create", $response['data']['events']); - $this->assertContains("users.*.verification.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.verification.*.create', $response['data']['events']); + $this->assertContains('users.*.verification.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $lastEmail = $this->getLastEmail(); $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); @@ -399,7 +397,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $session, + 'cookie' => 'a_session_'.$projectId.'='.$session, ]), [ 'userId' => $userId, 'secret' => $verification, @@ -414,7 +412,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.verification.{$verificationId}.update", $response['data']['events']); $this->assertContains("users.{$userId}.verification.{$verificationId}", $response['data']['events']); $this->assertContains("users.{$userId}.verification.*.update", $response['data']['events']); @@ -422,9 +420,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}.update", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}", $response['data']['events']); - $this->assertContains("users.*.verification.*.update", $response['data']['events']); - $this->assertContains("users.*.verification.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.verification.*.update', $response['data']['events']); + $this->assertContains('users.*.verification.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); /** * Test Acoount Prefs Update */ @@ -432,12 +430,12 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $session, + 'cookie' => 'a_session_'.$projectId.'='.$session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ] + ], ]); $response = json_decode($client->receive(), true); @@ -449,13 +447,13 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.prefs", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains("users.*.update.prefs", $response['data']['events']); - $this->assertContains("users.*.update", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.update.prefs', $response['data']['events']); + $this->assertContains('users.*.update', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $createSession = function () use ($projectId): array { @@ -468,10 +466,10 @@ class RealtimeCustomClientTest extends Scope 'password' => 'new-password', ]); - $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $projectId]; + $sessionNew = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$projectId]; $sessionNewId = $response['body']['$id']; - return array("session" => $sessionNew, "sessionId" => $sessionNewId); + return ['session' => $sessionNew, 'sessionId' => $sessionNewId]; }; /** @@ -490,7 +488,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}.create", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.*.create", $response['data']['events']); @@ -498,19 +496,19 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}.create", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']); - $this->assertContains("users.*.sessions.*.create", $response['data']['events']); - $this->assertContains("users.*.sessions.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.sessions.*.create', $response['data']['events']); + $this->assertContains('users.*.sessions.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test Account Session Delete */ - $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionNewId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_' . $projectId . '=' . $sessionNew, + 'cookie' => 'a_session_'.$projectId.'='.$sessionNew, ])); $response = json_decode($client->receive(), true); @@ -522,7 +520,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.*.delete", $response['data']['events']); @@ -530,21 +528,20 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']); - $this->assertContains("users.*.sessions.*.delete", $response['data']['events']); - $this->assertContains("users.*.sessions.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.sessions.*.delete', $response['data']['events']); + $this->assertContains('users.*.sessions.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test User Account Session Delete */ - $sessionData = $createSession(); $sessionNew = $sessionData['session']; $sessionNewId = $sessionData['sessionId']; $client->receive(); // Receive the creation message and drop; this was tested earlier already - $this->client->call(Client::METHOD_DELETE, '/users/' . $userId . '/sessions/' . $sessionNewId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/users/'.$userId.'/sessions/'.$sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, @@ -559,7 +556,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.*.delete", $response['data']['events']); @@ -567,9 +564,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']); - $this->assertContains("users.*.sessions.*.delete", $response['data']['events']); - $this->assertContains("users.*.sessions.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.sessions.*.delete', $response['data']['events']); + $this->assertContains('users.*.sessions.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** @@ -596,7 +593,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}.create", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.*.create", $response['data']['events']); @@ -604,9 +601,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}.create", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}", $response['data']['events']); - $this->assertContains("users.*.recovery.*.create", $response['data']['events']); - $this->assertContains("users.*.recovery.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.recovery.*.create', $response['data']['events']); + $this->assertContains('users.*.recovery.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $response = $this->client->call(Client::METHOD_PUT, '/account/recovery', array_merge([ @@ -629,7 +626,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('account.'.$userId, $response['data']['channels']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}.update", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.*.update", $response['data']['events']); @@ -637,9 +634,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}.update", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}", $response['data']['events']); - $this->assertContains("users.*.recovery.*.update", $response['data']['events']); - $this->assertContains("users.*.recovery.*", $response['data']['events']); - $this->assertContains("users.*", $response['data']['events']); + $this->assertContains('users.*.recovery.*.update', $response['data']['events']); + $this->assertContains('users.*.recovery.*', $response['data']['events']); + $this->assertContains('users.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); @@ -653,7 +650,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['documents', 'collections'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -674,7 +671,7 @@ class RealtimeCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'Actors DB', @@ -685,10 +682,10 @@ class RealtimeCustomClientTest extends Scope /** * Test Collection Create */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -700,10 +697,10 @@ class RealtimeCustomClientTest extends Scope $actorsId = $actors['body']['$id']; - $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ + $name = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 256, @@ -721,13 +718,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Create */ - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Chris Evans' + 'name' => 'Chris Evans', ], 'permissions' => [ Permission::read(Role::any()), @@ -747,8 +744,8 @@ class RealtimeCustomClientTest extends Scope $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); - $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents.' . $documentId, $response['data']['channels']); - $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents', $response['data']['channels']); + $this->assertContains('databases.'.$databaseId.'.collections.'.$actorsId.'.documents.'.$documentId, $response['data']['channels']); + $this->assertContains('databases.'.$databaseId.'.collections.'.$actorsId.'.documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $response['data']['events']); @@ -760,20 +757,20 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans'); /** * Test Document Update */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Chris Evans 2' + 'name' => 'Chris Evans 2', ], 'permissions' => [ Permission::read(Role::any()), @@ -804,7 +801,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2'); @@ -812,13 +809,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Delete */ - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Bradley Cooper' + 'name' => 'Bradley Cooper', ], 'permissions' => [ Permission::read(Role::any()), @@ -831,7 +828,7 @@ class RealtimeCustomClientTest extends Scope $documentId = $document['body']['$id']; - $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -858,7 +855,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper'); @@ -873,7 +870,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['documents', 'collections'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -894,7 +891,7 @@ class RealtimeCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'databaseId' => ID::unique(), 'name' => 'Actors DB', @@ -905,10 +902,10 @@ class RealtimeCustomClientTest extends Scope /** * Test Collection Create */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -917,15 +914,15 @@ class RealtimeCustomClientTest extends Scope Permission::create(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), - ] + ], ]); $actorsId = $actors['body']['$id']; - $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ + $name = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'name', 'size' => 256, @@ -943,13 +940,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Create */ - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Chris Evans' + 'name' => 'Chris Evans', ], 'permissions' => [], ]); @@ -978,19 +975,19 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans'); /** * Test Document Update */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ - 'name' => 'Chris Evans 2' + 'name' => 'Chris Evans 2', ], 'permissions' => [], ]); @@ -1017,7 +1014,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2'); @@ -1025,13 +1022,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Delete */ - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Bradley Cooper' + 'name' => 'Bradley Cooper', ], 'permissions' => [], ]); @@ -1040,7 +1037,7 @@ class RealtimeCustomClientTest extends Scope $client->receive(); - $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1067,7 +1064,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains("databases.*", $response['data']['events']); + $this->assertContains('databases.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper'); @@ -1082,7 +1079,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['files'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -1101,7 +1098,7 @@ class RealtimeCustomClientTest extends Scope $bucket1 = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'bucketId' => ID::unique(), 'name' => 'Bucket 1', @@ -1110,7 +1107,7 @@ class RealtimeCustomClientTest extends Scope Permission::create(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), - ] + ], ]); $bucketId = $bucket1['body']['$id']; @@ -1118,12 +1115,12 @@ class RealtimeCustomClientTest extends Scope /** * Test File Create */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -1151,9 +1148,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("buckets.{$bucketId}", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}.create", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']); - $this->assertContains("buckets.*.files.*.create", $response['data']['events']); - $this->assertContains("buckets.*.files.*", $response['data']['events']); - $this->assertContains("buckets.*", $response['data']['events']); + $this->assertContains('buckets.*.files.*.create', $response['data']['events']); + $this->assertContains('buckets.*.files.*', $response['data']['events']); + $this->assertContains('buckets.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $fileId = $file['body']['$id']; @@ -1161,7 +1158,7 @@ class RealtimeCustomClientTest extends Scope /** * Test File Update */ - $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1190,15 +1187,15 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("buckets.{$bucketId}", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}.update", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']); - $this->assertContains("buckets.*.files.*.update", $response['data']['events']); - $this->assertContains("buckets.*.files.*", $response['data']['events']); - $this->assertContains("buckets.*", $response['data']['events']); + $this->assertContains('buckets.*.files.*.update', $response['data']['events']); + $this->assertContains('buckets.*.files.*', $response['data']['events']); + $this->assertContains('buckets.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test File Delete */ - $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1221,9 +1218,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("buckets.{$bucketId}", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}.delete", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']); - $this->assertContains("buckets.*.files.*.delete", $response['data']['events']); - $this->assertContains("buckets.*.files.*", $response['data']['events']); - $this->assertContains("buckets.*", $response['data']['events']); + $this->assertContains('buckets.*.files.*.delete', $response['data']['events']); + $this->assertContains('buckets.*.files.*', $response['data']['events']); + $this->assertContains('buckets.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); @@ -1237,7 +1234,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['executions'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -1257,7 +1254,7 @@ class RealtimeCustomClientTest extends Scope $function = $this->client->call(Client::METHOD_POST, '/functions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'functionId' => ID::unique(), 'name' => 'Test', @@ -1274,18 +1271,18 @@ class RealtimeCustomClientTest extends Scope $folder = 'timeout'; $stderr = ''; $stdout = ''; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz"; + $code = realpath(__DIR__.'/../../../resources/functions')."/{$folder}/code.tar.gz"; - Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); + Console::execute('cd '.realpath(__DIR__.'/../../../resources/functions')."/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), - 'activate' => true + 'activate' => true, ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -1296,20 +1293,20 @@ class RealtimeCustomClientTest extends Scope // Wait for deployment to be built. sleep(10); - $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']['$id']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'async' => true + 'async' => true, ]); $this->assertEquals($execution['headers']['status-code'], 202); @@ -1337,9 +1334,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("functions.{$functionId}", $response['data']['events']); $this->assertContains("functions.*.executions.{$executionId}.create", $response['data']['events']); $this->assertContains("functions.*.executions.{$executionId}", $response['data']['events']); - $this->assertContains("functions.*.executions.*.create", $response['data']['events']); - $this->assertContains("functions.*.executions.*", $response['data']['events']); - $this->assertContains("functions.*", $response['data']['events']); + $this->assertContains('functions.*.executions.*.create', $response['data']['events']); + $this->assertContains('functions.*.executions.*', $response['data']['events']); + $this->assertContains('functions.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertArrayHasKey('type', $responseUpdate); @@ -1359,15 +1356,15 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("functions.{$functionId}", $responseUpdate['data']['events']); $this->assertContains("functions.*.executions.{$executionId}.update", $responseUpdate['data']['events']); $this->assertContains("functions.*.executions.{$executionId}", $responseUpdate['data']['events']); - $this->assertContains("functions.*.executions.*.update", $responseUpdate['data']['events']); - $this->assertContains("functions.*.executions.*", $responseUpdate['data']['events']); - $this->assertContains("functions.*", $responseUpdate['data']['events']); + $this->assertContains('functions.*.executions.*.update', $responseUpdate['data']['events']); + $this->assertContains('functions.*.executions.*', $responseUpdate['data']['events']); + $this->assertContains('functions.*', $responseUpdate['data']['events']); $this->assertNotEmpty($responseUpdate['data']['payload']); $client->close(); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1384,7 +1381,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['teams'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -1406,7 +1403,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal' + 'name' => 'Arsenal', ]); $teamId = $team['body']['$id'] ?? ''; @@ -1426,18 +1423,18 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}", $response['data']['channels']); $this->assertContains("teams.{$teamId}.create", $response['data']['events']); $this->assertContains("teams.{$teamId}", $response['data']['events']); - $this->assertContains("teams.*.create", $response['data']['events']); - $this->assertContains("teams.*", $response['data']['events']); + $this->assertContains('teams.*.create', $response['data']['events']); + $this->assertContains('teams.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test Team Update */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId, array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ - 'name' => 'Manchester' + 'name' => 'Manchester', ]); $this->assertEquals($team['headers']['status-code'], 200); @@ -1455,21 +1452,21 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}", $response['data']['channels']); $this->assertContains("teams.{$teamId}.update", $response['data']['events']); $this->assertContains("teams.{$teamId}", $response['data']['events']); - $this->assertContains("teams.*.update", $response['data']['events']); - $this->assertContains("teams.*", $response['data']['events']); + $this->assertContains('teams.*.update', $response['data']['events']); + $this->assertContains('teams.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test Team Update Prefs */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId . '/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId.'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'prefs' => [ 'funcKey1' => 'funcValue1', 'funcKey2' => 'funcValue2', - ] + ], ]); $this->assertEquals($team['headers']['status-code'], 200); @@ -1489,9 +1486,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}.update", $response['data']['events']); $this->assertContains("teams.{$teamId}.update.prefs", $response['data']['events']); $this->assertContains("teams.{$teamId}", $response['data']['events']); - $this->assertContains("teams.*.update.prefs", $response['data']['events']); - $this->assertContains("teams.*.update", $response['data']['events']); - $this->assertContains("teams.*", $response['data']['events']); + $this->assertContains('teams.*.update.prefs', $response['data']['events']); + $this->assertContains('teams.*.update', $response['data']['events']); + $this->assertContains('teams.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['funcKey1'], 'funcValue1'); $this->assertEquals($response['data']['payload']['funcKey2'], 'funcValue2'); @@ -1514,7 +1511,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['memberships'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_' . $projectId . '=' . $session + 'cookie' => 'a_session_'.$projectId.'='.$session, ]); $response = json_decode($client->receive(), true); @@ -1528,7 +1525,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']['user']); $this->assertEquals($user['$id'], $response['data']['user']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1539,12 +1536,12 @@ class RealtimeCustomClientTest extends Scope * Test Update Membership */ $roles = ['admin', 'editor', 'uncle']; - $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamId . '/memberships/' . $membershipId, array_merge([ + $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamId.'/memberships/'.$membershipId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => $roles, ]); $response = json_decode($client->receive(), true); @@ -1564,9 +1561,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}", $response['data']['events']); $this->assertContains("teams.*.memberships.{$membershipId}.update", $response['data']['events']); $this->assertContains("teams.*.memberships.{$membershipId}", $response['data']['events']); - $this->assertContains("teams.*.memberships.*.update", $response['data']['events']); - $this->assertContains("teams.*.memberships.*", $response['data']['events']); - $this->assertContains("teams.*", $response['data']['events']); + $this->assertContains('teams.*.memberships.*.update', $response['data']['events']); + $this->assertContains('teams.*.memberships.*', $response['data']['events']); + $this->assertContains('teams.*', $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index b19fe49ed0..9b0a6449d3 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -4,7 +4,6 @@ namespace Tests\E2E\Services\Storage; use CURLFile; use Tests\E2E\Client; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -26,7 +25,7 @@ trait StorageBase 'name' => 'Test Bucket', 'fileSecurity' => true, 'maximumFileSize' => 2000000, //2MB - 'allowedFileExtensions' => ["jpg", "png"], + 'allowedFileExtensions' => ['jpg', 'png'], 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -39,12 +38,12 @@ trait StorageBase $bucketId = $bucket['body']['$id']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -58,7 +57,7 @@ trait StorageBase $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $this->assertTrue(md5_file(realpath(__DIR__ . '/../../../resources/logo.png')) == $file['body']['signature']); + $this->assertTrue(md5_file(realpath(__DIR__.'/../../../resources/logo.png')) == $file['body']['signature']); /** * Test for Large File above 20MB * This should also validate the test for when Bucket encryption @@ -85,27 +84,26 @@ trait StorageBase /** * Chunked Upload */ - - $source = __DIR__ . "/../../../resources/disk-a/large-file.mp4"; + $source = __DIR__.'/../../../resources/disk-a/large-file.mp4'; $totalSize = \filesize($source); $chunkSize = 5 * 1024 * 1024; - $handle = @fopen($source, "rb"); + $handle = @fopen($source, 'rb'); $fileId = 'unique()'; $mimeType = mime_content_type($source); $counter = 0; $size = filesize($source); $headers = [ 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ]; $id = ''; - while (!feof($handle)) { - $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); - $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; - if (!empty($id)) { + while (! feof($handle)) { + $curlFile = new \CURLFile('data://'.$mimeType.';base64,'.base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); + $headers['content-range'] = 'bytes '.($counter * $chunkSize).'-'.min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1).'/'.$size; + if (! empty($id)) { $headers['x-appwrite-id'] = $id; } - $largeFile = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', array_merge($headers, $this->getHeaders()), [ + $largeFile = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucket2['body']['$id'].'/files', array_merge($headers, $this->getHeaders()), [ 'fileId' => $fileId, 'file' => $curlFile, 'permissions' => [ @@ -125,28 +123,28 @@ trait StorageBase $this->assertEquals('large-file.mp4', $largeFile['body']['name']); $this->assertEquals('video/mp4', $largeFile['body']['mimeType']); $this->assertEquals($totalSize, $largeFile['body']['sizeOriginal']); - $this->assertEquals(md5_file(realpath(__DIR__ . '/../../../resources/disk-a/large-file.mp4')), $largeFile['body']['signature']); // should validate that the file is not encrypted + $this->assertEquals(md5_file(realpath(__DIR__.'/../../../resources/disk-a/large-file.mp4')), $largeFile['body']['signature']); // should validate that the file is not encrypted /** * Failure * Test for Chunk above 5MB */ - $source = __DIR__ . "/../../../resources/disk-a/large-file.mp4"; + $source = __DIR__.'/../../../resources/disk-a/large-file.mp4'; $totalSize = \filesize($source); $chunkSize = 6 * 1024 * 1024; - $handle = @fopen($source, "rb"); + $handle = @fopen($source, 'rb'); $fileId = 'unique()'; $mimeType = mime_content_type($source); $counter = 0; $size = filesize($source); $headers = [ 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ]; $id = ''; - $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); - $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', $this->getHeaders(), [ + $curlFile = new \CURLFile('data://'.$mimeType.';base64,'.base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); + $headers['content-range'] = 'bytes '.($counter * $chunkSize).'-'.min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1).'/'.$size; + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucket2['body']['$id'].'/files', $this->getHeaders(), [ 'fileId' => $fileId, 'file' => $curlFile, 'permissions' => [ @@ -159,17 +157,15 @@ trait StorageBase $this->assertEquals(413, $res['headers']['status-code']); - /** * Test for FAILURE unknown Bucket */ - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/empty/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -181,13 +177,12 @@ trait StorageBase /** * Test for FAILURE file above bucket's file size limit */ - - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-b/kitten-1.png'), 'image/png', 'kitten-1.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/disk-b/kitten-1.png'), 'image/png', 'kitten-1.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -201,13 +196,12 @@ trait StorageBase /** * Test for FAILURE unsupported bucket file extension */ - - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-a/kitten-3.gif'), 'image/gif', 'kitten-3.gif'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/disk-a/kitten-3.gif'), 'image/gif', 'kitten-3.gif'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -230,7 +224,7 @@ trait StorageBase 'name' => 'Test Bucket 2', 'fileSecurity' => true, 'maximumFileSize' => 200000000, //200MB - 'allowedFileExtensions' => ["jpg", "png"], + 'allowedFileExtensions' => ['jpg', 'png'], 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -244,12 +238,12 @@ trait StorageBase /** * Test for FAILURE set x-appwrite-id to unique() */ - $source = realpath(__DIR__ . '/../../../resources/logo.png'); + $source = realpath(__DIR__.'/../../../resources/logo.png'); $totalSize = \filesize($source); - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'content-range' => 'bytes 0-' . $size . '/' . $size, + 'content-range' => 'bytes 0-'.$size.'/'.$size, 'x-appwrite-id' => 'unique()', ], $this->getHeaders()), [ 'fileId' => ID::unique(), @@ -278,7 +272,7 @@ trait StorageBase 'name' => 'Test Bucket', 'fileSecurity' => true, 'maximumFileSize' => 2000000, //2MB - 'allowedFileExtensions' => ["jpg", "png"], + 'allowedFileExtensions' => ['jpg', 'png'], 'compression' => 'zstd', 'permissions' => [ Permission::read(Role::any()), @@ -293,12 +287,12 @@ trait StorageBase $bucketId = $bucket['body']['$id']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -311,7 +305,7 @@ trait StorageBase $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $this->assertTrue(md5_file(realpath(__DIR__ . '/../../../resources/logo.png')) == $file['body']['signature']); + $this->assertTrue(md5_file(realpath(__DIR__.'/../../../resources/logo.png')) == $file['body']['signature']); return ['bucketId' => $bucketId]; } @@ -324,7 +318,7 @@ trait StorageBase /** * Test for SUCCESS */ - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -332,38 +326,38 @@ trait StorageBase $this->assertGreaterThan(0, $files['body']['total']); $this->assertGreaterThan(0, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ] + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(1, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ] + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(0, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("mimeType", "image/png")' ] + 'queries' => ['equal("mimeType", "image/png")'], ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(1, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("mimeType", "image/jpeg")' ] + 'queries' => ['equal("mimeType", "image/jpeg")'], ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(0, count($files['body']['files'])); @@ -371,7 +365,6 @@ trait StorageBase /** * Test for FAILURE unknown Bucket */ - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -390,7 +383,7 @@ trait StorageBase /** * Test for SUCCESS */ - $file1 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'], array_merge([ + $file1 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -404,7 +397,7 @@ trait StorageBase $this->assertIsArray($file1['body']['$permissions']); $this->assertCount(3, $file1['body']['$permissions']); - $file2 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ + $file2 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -414,7 +407,7 @@ trait StorageBase $this->assertNotEmpty($file2['body']); //new image preview features - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -432,13 +425,13 @@ trait StorageBase $image = new \Imagick(); $image->readImageBlob($file3['body']); - $original = new \Imagick(__DIR__ . '/../../../resources/logo-after.png'); + $original = new \Imagick(__DIR__.'/../../../resources/logo-after.png'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $file4 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ + $file4 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -455,13 +448,13 @@ trait StorageBase $image = new \Imagick(); $image->readImageBlob($file4['body']); - $original = new \Imagick(__DIR__ . '/../../../resources/logo-after.jpg'); + $original = new \Imagick(__DIR__.'/../../../resources/logo-after.jpg'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); $this->assertEquals('JPEG', $image->getImageFormat()); - $file5 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ + $file5 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -472,13 +465,13 @@ trait StorageBase $this->assertNotEmpty($file5['body']); // Test ranged download - $file51 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ + $file51 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=0-99', ], $this->getHeaders())); - $path = __DIR__ . '/../../../resources/logo.png'; + $path = __DIR__.'/../../../resources/logo.png'; $originalChunk = \file_get_contents($path, false, null, 0, 100); $this->assertEquals(206, $file51['headers']['status-code']); @@ -488,7 +481,7 @@ trait StorageBase $this->assertEquals($originalChunk, $file51['body']); // Test ranged download - with invalid range - $file52 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ + $file52 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=0-', @@ -497,7 +490,7 @@ trait StorageBase $this->assertEquals(206, $file52['headers']['status-code']); // Test ranged download - with invalid range - $file53 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ + $file53 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=988', @@ -506,7 +499,7 @@ trait StorageBase $this->assertEquals(416, $file53['headers']['status-code']); // Test ranged download - with invalid range - $file54 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ + $file54 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=-988', @@ -514,7 +507,7 @@ trait StorageBase $this->assertEquals(416, $file54['headers']['status-code']); - $file6 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/view', array_merge([ + $file6 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -524,7 +517,7 @@ trait StorageBase $this->assertNotEmpty($file6['body']); // Test for negative angle values in fileGetPreview - $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ + $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -542,7 +535,7 @@ trait StorageBase $image = new \Imagick(); $image->readImageBlob($file7['body']); - $original = new \Imagick(__DIR__ . '/../../../resources/logo-after.png'); + $original = new \Imagick(__DIR__.'/../../../resources/logo-after.png'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); @@ -551,7 +544,7 @@ trait StorageBase /** * Test large files decompress successfully */ - $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['largeBucketId'] . '/files/' . $data['largeFileId'] . '/download', array_merge([ + $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['largeBucketId'].'/files/'.$data['largeFileId'].'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -560,17 +553,16 @@ trait StorageBase $this->assertEquals('attachment; filename="large-file.mp4"', $file7['headers']['content-disposition']); $this->assertEquals('video/mp4', $file7['headers']['content-type']); $this->assertNotEmpty($fileData); - $this->assertEquals(md5_file(realpath(__DIR__ . '/../../../resources/disk-a/large-file.mp4')), md5($fileData)); // validate the file is downloaded correctly + $this->assertEquals(md5_file(realpath(__DIR__.'/../../../resources/disk-a/large-file.mp4')), md5($fileData)); // validate the file is downloaded correctly /** * Test for FAILURE unknown Bucket */ - - $file8 = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty/files/' . $data['fileId'], array_merge([ + $file8 = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 2 + 'limit' => 2, ]); $this->assertEquals(404, $file8['headers']['status-code']); @@ -585,12 +577,12 @@ trait StorageBase { $bucketId = $data['bucketId']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::custom('testcache'), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -603,7 +595,7 @@ trait StorageBase $fileId = $file['body']['$id']; //get image preview - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -622,7 +614,7 @@ trait StorageBase $imageBefore = new \Imagick(); $imageBefore->readImageBlob($file3['body']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$data['bucketId'].'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -631,12 +623,12 @@ trait StorageBase $this->assertEmpty($file['body']); sleep(1); //upload again using the same ID - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::custom('testcache'), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-b/kitten-2.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/disk-b/kitten-2.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -647,7 +639,7 @@ trait StorageBase $this->assertNotEmpty($file['body']['$id']); //get image preview after - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -678,12 +670,12 @@ trait StorageBase { $bucketId = $data['bucketId']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -696,7 +688,7 @@ trait StorageBase $fileId = $file['body']['$id']; //get image preview - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -723,7 +715,7 @@ trait StorageBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -732,7 +724,7 @@ trait StorageBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -754,8 +746,7 @@ trait StorageBase /** * Test for FAILURE unknown Bucket */ - - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/empty/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/empty/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -763,7 +754,7 @@ trait StorageBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals(404, $file['headers']['status-code']); @@ -779,7 +770,7 @@ trait StorageBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -787,7 +778,7 @@ trait StorageBase $this->assertEquals(204, $file['headers']['status-code']); $this->assertEmpty($file['body']); - $file = $this->client->call(Client::METHOD_GET, '/storage/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index aff055f18d..2d473c5c73 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Storage; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; use Utopia\Database\Helpers\ID; @@ -21,9 +21,9 @@ class StorageConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_GET, '/storage/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '32h' + 'range' => '32h', ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -33,9 +33,9 @@ class StorageConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_GET, '/storage/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -55,7 +55,7 @@ class StorageConsoleClientTest extends Scope ], $this->getHeaders()), [ 'bucketId' => ID::unique(), 'name' => 'Test Bucket', - 'permission' => 'file' + 'permission' => 'file', ]); $this->assertEquals(201, $bucket['headers']['status-code']); $bucketId = $bucket['body']['$id']; @@ -63,12 +63,11 @@ class StorageConsoleClientTest extends Scope /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/storage/' . $bucketId . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/storage/'.$bucketId.'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '32h' + 'range' => '32h', ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -77,9 +76,9 @@ class StorageConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/storage/randomBucketId/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals($response['headers']['status-code'], 404); @@ -87,11 +86,11 @@ class StorageConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/storage/' . $bucketId . '/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/storage/'.$bucketId.'/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'range' => '24h' + 'range' => '24h', ]); $this->assertEquals($response['headers']['status-code'], 200); diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index 12fc006968..f9ca64644a 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -4,10 +4,9 @@ namespace Tests\E2E\Services\Storage; use CURLFile; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -46,13 +45,13 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -63,14 +62,14 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -83,14 +82,14 @@ class StorageCustomClientTest extends Scope $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -101,14 +100,14 @@ class StorageCustomClientTest extends Scope $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -120,35 +119,34 @@ class StorageCustomClientTest extends Scope public function testBucketAnyPermissions(): void { - /** * Test for SUCCESS */ $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'bucketId' => ID::unique(), - 'name' => 'Test Bucket', - 'permissions' => [ - Permission::read(Role::any()), - Permission::create(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ - 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -159,46 +157,46 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'name' => 'permissions.png', + 'name' => 'permissions.png', ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(204, $file['headers']['status-code']); @@ -229,12 +227,12 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -245,35 +243,35 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -285,24 +283,24 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -311,7 +309,7 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -321,7 +319,7 @@ class StorageCustomClientTest extends Scope /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -354,12 +352,12 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -370,35 +368,35 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -410,22 +408,22 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); - $this->client->call(CLient::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $this->client->call(CLient::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -436,50 +434,50 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals($file['headers']['status-code'], 401); - $email = ID::unique() . '@localhost.test'; + $email = ID::unique().'@localhost.test'; $password = 'password'; $user2 = $this->createUser('user2', $email, $password); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'permissions' => [], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -487,12 +485,11 @@ class StorageCustomClientTest extends Scope /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(204, $file['headers']['status-code']); $this->assertEmpty($file['body']); } @@ -501,8 +498,8 @@ class StorageCustomClientTest extends Scope { $team1 = $this->createTeam(ID::unique(), 'Team 1'); $team2 = $this->createTeam(ID::unique(), 'Team 1'); - $user1 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); - $user2 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); + $user1 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); + $user2 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); $this->addToTeam($user1['$id'], $team1['$id']); $this->addToTeam($user2['$id'], $team2['$id']); @@ -531,13 +528,13 @@ class StorageCustomClientTest extends Scope $this->assertNotEmpty($bucketId); // Team 1 create success - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -549,73 +546,73 @@ class StorageCustomClientTest extends Scope $this->assertEquals(47218, $file['body']['sizeOriginal']); // Team 1 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -625,22 +622,22 @@ class StorageCustomClientTest extends Scope */ // Team 2 create failure - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); // Team 2 update failure - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'permissions' => [], ]); @@ -648,10 +645,10 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); // Team 2 delete failure - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -660,10 +657,10 @@ class StorageCustomClientTest extends Scope * Test for SUCCESS */ // Team 1 delete success - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(204, $file['headers']['status-code']); @@ -683,20 +680,20 @@ class StorageCustomClientTest extends Scope 'bucketId' => ID::unique(), 'name' => 'Test Bucket', 'permissions' => [], - 'fileSecurity' => true + 'fileSecurity' => true, ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::any()), ], @@ -710,28 +707,28 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -741,17 +738,17 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -772,20 +769,20 @@ class StorageCustomClientTest extends Scope 'bucketId' => ID::unique(), 'name' => 'Test Bucket', 'permissions' => [], - 'fileSecurity' => true + 'fileSecurity' => true, ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::users()), ], @@ -799,28 +796,28 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -830,17 +827,17 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -861,20 +858,20 @@ class StorageCustomClientTest extends Scope 'bucketId' => ID::unique(), 'name' => 'Test Bucket', 'permissions' => [], - 'fileSecurity' => true + 'fileSecurity' => true, ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), ], @@ -888,28 +885,28 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -919,58 +916,58 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(401, $file['headers']['status-code']); - $user2 = $this->createUser(ID::unique(), uniqid() . '@localhost.test', 'password'); + $user2 = $this->createUser(ID::unique(), uniqid().'@localhost.test', 'password'); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 404); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'permissions' => [], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -980,8 +977,8 @@ class StorageCustomClientTest extends Scope { $team1 = $this->createTeam(ID::unique(), 'Team 1'); $team2 = $this->createTeam(ID::unique(), 'Team 1'); - $user1 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); - $user2 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); + $user1 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); + $user2 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); $this->addToTeam($user1['$id'], $team1['$id']); $this->addToTeam($user2['$id'], $team2['$id']); @@ -1004,13 +1001,13 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::team(ID::custom($team1['$id']))), Permission::read(Role::team(ID::custom($team2['$id']))), @@ -1028,73 +1025,73 @@ class StorageCustomClientTest extends Scope $this->assertEquals(47218, $file['body']['sizeOriginal']); // Team 1 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -1104,32 +1101,32 @@ class StorageCustomClientTest extends Scope */ // Team 1 create failure - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); // Team 2 create failure - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); // Team 2 update failure - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ], [ 'permissions' => [], ]); @@ -1137,10 +1134,10 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); // Team 2 delete failure - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -1149,10 +1146,10 @@ class StorageCustomClientTest extends Scope * Test for SUCCESS */ // Team 1 delete success - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], ]); $this->assertEquals(204, $file['headers']['status-code']); @@ -1187,15 +1184,15 @@ class StorageCustomClientTest extends Scope $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $bucket['body']['$permissions']); // File aliases write to update, delete - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::write(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertNotContains(Permission::create(Role::user($this->getUser()['$id'])), $file1['body']['$permissions']); @@ -1207,15 +1204,15 @@ class StorageCustomClientTest extends Scope */ // File does not allow create permission - $file2 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + $file2 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), - ] + ], ]); $this->assertEquals(400, $file2['headers']['status-code']); @@ -1244,12 +1241,12 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket['body']['$id'] . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucket['body']['$id'].'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 201); @@ -1273,12 +1270,12 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'folderId' => ID::custom('xyz'), 'permissions' => [ Permission::read(Role::user(ID::custom('notme'))), @@ -1289,33 +1286,33 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'folderId' => ID::custom('xyz'), 'permissions' => [ Permission::update(Role::user(ID::custom('notme'))), Permission::delete(Role::user(ID::custom('notme'))), - ] + ], ]); $this->assertEquals(401, $file['headers']['status-code']); $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'folderId' => ID::custom('xyz'), 'permissions' => [ Permission::read(Role::user(ID::custom('notme'))), @@ -1328,7 +1325,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); } /** @@ -1339,7 +1336,7 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1352,25 +1349,25 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'permissions' => [ Permission::update(Role::user(ID::custom('notme'))), Permission::delete(Role::user(ID::custom('notme'))), - ] + ], ]); $this->assertEquals(401, $file['headers']['status-code']); $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1385,6 +1382,6 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); } } diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 38fb0e0b9d..2da95f7983 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -83,8 +83,8 @@ class StorageCustomServerTest extends Scope '/storage/buckets', array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -98,7 +98,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ], + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -108,7 +108,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ], + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -118,7 +118,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("$id", "bucket1")' ], + 'queries' => ['equal("$id", "bucket1")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -128,7 +128,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("fileSecurity", true)' ], + 'queries' => ['equal("fileSecurity", true)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -138,7 +138,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("' . $response['body']['buckets'][0]['$id'] . '")' ], + 'queries' => ['cursorAfter("'.$response['body']['buckets'][0]['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -147,6 +147,7 @@ class StorageCustomServerTest extends Scope $this->assertCount(1, $response['body']['buckets']); $this->assertEquals('bucket1', $response['body']['buckets'][0]['$id']); + return $data; } @@ -161,11 +162,11 @@ class StorageCustomServerTest extends Scope */ $response = $this->client->call( Client::METHOD_GET, - '/storage/buckets/' . $id, + '/storage/buckets/'.$id, array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -178,14 +179,13 @@ class StorageCustomServerTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call( Client::METHOD_GET, '/storage/buckets/empty', array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -197,8 +197,8 @@ class StorageCustomServerTest extends Scope '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -217,7 +217,7 @@ class StorageCustomServerTest extends Scope /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $id, array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -239,7 +239,7 @@ class StorageCustomServerTest extends Scope /** * Test for FAILURE */ - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $id, array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -262,11 +262,11 @@ class StorageCustomServerTest extends Scope */ $response = $this->client->call( Client::METHOD_DELETE, - '/storage/buckets/' . $id, + '/storage/buckets/'.$id, array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -276,11 +276,11 @@ class StorageCustomServerTest extends Scope $response = $this->client->call( Client::METHOD_GET, - '/storage/buckets/' . $id, + '/storage/buckets/'.$id, array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) diff --git a/tests/e2e/Services/Storage/StoragePermissionsScope.php b/tests/e2e/Services/Storage/StoragePermissionsScope.php index 09b35fad36..e6502cc183 100644 --- a/tests/e2e/Services/Storage/StoragePermissionsScope.php +++ b/tests/e2e/Services/Storage/StoragePermissionsScope.php @@ -7,6 +7,7 @@ use Tests\E2E\Client; trait StoragePermissionsScope { public array $users = []; + public array $teams = []; public function createUser(string $id, string $email, string $password = 'test123!'): array @@ -18,7 +19,7 @@ trait StoragePermissionsScope ], [ 'userId' => $id, 'email' => $email, - 'password' => $password + 'password' => $password, ]); $this->assertEquals(201, $user['headers']['status-code']); @@ -32,8 +33,7 @@ trait StoragePermissionsScope 'password' => $password, ]); - $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; - + $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $user = [ '$id' => $user['body']['$id'], @@ -54,7 +54,7 @@ trait StoragePermissionsScope { $team = $this->client->call(Client::METHOD_POST, '/teams', $this->getServerHeader(), [ 'teamId' => $id, - 'name' => $name + 'name' => $name, ]); $this->teams[$id] = $team['body']; @@ -63,16 +63,16 @@ trait StoragePermissionsScope public function addToTeam(string $user, string $team, array $roles = []): array { - $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team . '/memberships', $this->getServerHeader(), [ + $membership = $this->client->call(Client::METHOD_POST, '/teams/'.$team.'/memberships', $this->getServerHeader(), [ 'teamId' => $team, 'email' => $this->getCreatedUser($user)['email'], 'roles' => $roles, - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); return [ 'user' => $membership['body']['userId'], - 'membership' => $membership['body']['$id'] + 'membership' => $membership['body']['$id'], ]; } @@ -81,7 +81,7 @@ trait StoragePermissionsScope return [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]; } } diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 83b9042f13..7b960b3aa5 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -3,7 +3,6 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -42,7 +41,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => $teamId, - 'name' => 'Manchester United' + 'name' => 'Manchester United', ]); $this->assertEquals(201, $response2['headers']['status-code']); @@ -59,7 +58,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Newcastle' + 'name' => 'Newcastle', ]); $this->assertEquals(201, $response3['headers']['status-code']); @@ -85,7 +84,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => $teamId, - 'name' => 'John' + 'name' => 'John', ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -104,7 +103,7 @@ trait TeamsBase /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -147,7 +146,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(2)' ], + 'queries' => ['limit(2)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -157,7 +156,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ], + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -167,7 +166,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'greaterThanEqual("total", 0)' ], + 'queries' => ['greaterThanEqual("total", 0)'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -177,7 +176,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("name", ["Arsenal", "Newcastle"])' ], + 'queries' => ['equal("name", ["Arsenal", "Newcastle"])'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -226,7 +225,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(2)' ], + 'queries' => ['limit(2)'], ]); $this->assertEquals(200, $teams['headers']['status-code']); @@ -238,7 +237,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)', 'cursorAfter("' . $teams['body']['teams'][0]['$id'] . '")' ], + 'queries' => ['limit(1)', 'cursorAfter("'.$teams['body']['teams'][0]['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -251,7 +250,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)', 'cursorBefore("' . $teams['body']['teams'][1]['$id'] . '")' ], + 'queries' => ['limit(1)', 'cursorBefore("'.$teams['body']['teams'][1]['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -267,7 +266,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("unknown")' ], + 'queries' => ['cursorAfter("unknown")'], ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -285,7 +284,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Demo' + 'name' => 'Demo', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -295,12 +294,12 @@ trait TeamsBase $this->assertIsInt($response['body']['total']); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); - $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/teams/'.$response['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Demo New' + 'name' => 'Demo New', ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -314,7 +313,7 @@ trait TeamsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/teams/'.$response['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -335,7 +334,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Demo' + 'name' => 'Demo', ]); $teamUid = $response['body']['$id']; @@ -349,7 +348,7 @@ trait TeamsBase $dateValidator = new DatetimeValidator(); $this->assertEquals(true, $dateValidator->isValid($response['body']['$createdAt'])); - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -360,7 +359,7 @@ trait TeamsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -380,7 +379,7 @@ trait TeamsBase /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $id . '/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$id.'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -394,7 +393,7 @@ trait TeamsBase $this->assertEquals($team['body']['funcKey1'], 'funcValue1'); $this->assertEquals($team['body']['funcKey2'], 'funcValue2'); - $team = $this->client->call(Client::METHOD_GET, '/teams/' . $id . '/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/'.$id.'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -405,7 +404,7 @@ trait TeamsBase 'funcKey2' => 'funcValue2', ]); - $team = $this->client->call(Client::METHOD_GET, '/teams/' . $id, array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -419,7 +418,7 @@ trait TeamsBase /** * Test for FAILURE */ - $user = $this->client->call(Client::METHOD_PUT, '/teams/' . $id . '/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PUT, '/teams/'.$id.'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 7b6b439558..4a3a2859dd 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -3,7 +3,6 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -20,7 +19,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -36,51 +35,51 @@ trait TeamsBaseClient $membershipId = $response['body']['memberships'][0]['$id']; - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'limit(1)' ] + 'queries' => ['limit(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(1, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'offset(1)' ] + 'queries' => ['offset(1)'], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(0, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("confirm", true)' ] + 'queries' => ['equal("confirm", true)'], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(1, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'equal("confirm", false)' ] + 'queries' => ['equal("confirm", false)'], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(0, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => $this->getUser()['$id'] + 'search' => $this->getUser()['$id'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -92,11 +91,11 @@ trait TeamsBaseClient $this->assertContains('owner', $response['body']['memberships'][0]['roles']); $this->assertContains('player', $response['body']['memberships'][0]['roles']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => $membershipId + 'search' => $membershipId, ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -108,11 +107,11 @@ trait TeamsBaseClient $this->assertContains('owner', $response['body']['memberships'][0]['roles']); $this->assertContains('player', $response['body']['memberships'][0]['roles']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'unknown' + 'search' => 'unknown', ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -138,7 +137,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -157,15 +156,14 @@ trait TeamsBaseClient /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid . 'dasdasd', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'dasdasd', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -180,20 +178,20 @@ trait TeamsBaseClient { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid() . 'friend@localhost.test'; + $email = uniqid().'friend@localhost.test'; $name = 'Friend User'; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -211,7 +209,7 @@ trait TeamsBaseClient $this->assertEquals($email, $lastEmail['to'][0]['address']); $this->assertEquals($name, $lastEmail['to'][0]['name']); - $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); + $this->assertEquals('Invitation to '.$teamName.' Team at '.$this->getProject()['name'], $lastEmail['subject']); $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); @@ -221,7 +219,7 @@ trait TeamsBaseClient * Test with UserId * Create user */ - $secondEmail = uniqid() . 'foe@localhost.test'; + $secondEmail = uniqid().'foe@localhost.test'; $secondName = 'Another Foe'; $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'content-type' => 'application/json', @@ -230,7 +228,7 @@ trait TeamsBaseClient 'userId' => 'unique()', 'email' => $secondEmail, 'password' => 'password', - 'name' => $secondName + 'name' => $secondName, ]); $this->assertEquals(201, $response['headers']['status-code']); $userId = $response['body']['$id']; @@ -239,13 +237,13 @@ trait TeamsBaseClient * Test for UserID * Failure */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'userId' => 'abcdefdg', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -254,13 +252,13 @@ trait TeamsBaseClient * Test for UserID * SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'userId' => $userId, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -278,56 +276,55 @@ trait TeamsBaseClient $this->assertEquals($secondEmail, $lastEmail['to'][0]['address']); $this->assertEquals($secondName, $lastEmail['to'][0]['name']); - $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); + $this->assertEquals('Invitation to '.$teamName.' Team at '.$this->getProject()['name'], $lastEmail['subject']); /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(409, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => 'dasdkaskdjaskdjasjkd', 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => 'bad string', - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://example.com/join-us#title' // bad url + 'url' => 'http://example.com/join-us#title', // bad url ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -339,7 +336,7 @@ trait TeamsBaseClient 'membershipUid' => $membershipUid, 'userUid' => $userUid, 'email' => $email, - 'name' => $name + 'name' => $name, ]; } @@ -348,7 +345,7 @@ trait TeamsBaseClient */ public function testListTeamMemberships($data): void { - $memberships = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ + $memberships = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -358,11 +355,11 @@ trait TeamsBaseClient $this->assertNotEmpty($memberships['body']['memberships']); $this->assertCount(3, $memberships['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'cursorAfter("' . $memberships['body']['memberships'][0]['$id'] . '")' ] + 'queries' => ['cursorAfter("'.$memberships['body']['memberships'][0]['$id'].'")'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -387,7 +384,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -403,19 +400,18 @@ trait TeamsBaseClient $this->assertCount(2, $response['body']['roles']); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['joined'])); $this->assertEquals(true, $response['body']['confirm']); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $data['session'] = $session; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals(true, $response['body']['emailVerification']); - /** [START] TESTS TO CHECK PASSWORD UPDATE OF NEW USER CREATED USING TEAM INVITE */ /** * New User tries to update password without old password -> SHOULD PASS @@ -424,9 +420,9 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'password' => 'new-password' + 'password' => 'new-password', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -444,7 +440,7 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'password' => 'new-password', ]); @@ -457,10 +453,10 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'password' => 'newer-password', - 'oldPassword' => 'new-password' + 'oldPassword' => 'new-password', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -476,7 +472,7 @@ trait TeamsBaseClient /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -487,7 +483,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -498,7 +494,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -509,7 +505,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -520,7 +516,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -531,7 +527,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -558,12 +554,12 @@ trait TeamsBaseClient * Test for SUCCESS */ $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => $roles, ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -578,12 +574,12 @@ trait TeamsBaseClient /** * Test for unknown team */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . 'abc' . '/memberships/' . $membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.'abc'.'/memberships/'.$membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => $roles, ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -591,27 +587,26 @@ trait TeamsBaseClient /** * Test for unknown membership ID */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . 'abc', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.'abc', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => $roles, ]); $this->assertEquals(404, $response['headers']['status-code']); - /** * Test for when a user other than the owner tries to update membership */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ], [ - 'roles' => $roles + 'roles' => $roles, ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -620,7 +615,7 @@ trait TeamsBaseClient return $data; } - /** + /** * @depends testUpdateTeamMembershipRoles */ public function testDeleteTeamMembership($data): array @@ -629,7 +624,7 @@ trait TeamsBaseClient $membershipUid = $data['membershipUid'] ?? ''; $session = $data['session'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -646,11 +641,11 @@ trait TeamsBaseClient /** * Test deleting a membership that does not exists */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/dne', [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/dne', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -658,11 +653,11 @@ trait TeamsBaseClient /** * Test deleting another user's membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -674,17 +669,17 @@ trait TeamsBaseClient /** * Test for when a user other than the owner tries to delete their membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]); $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -695,7 +690,7 @@ trait TeamsBaseClient /** * Test for when the owner tries to delete their membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -704,7 +699,7 @@ trait TeamsBaseClient $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index 7bb6241c4a..642078d72b 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -17,7 +17,7 @@ trait TeamsBaseServer /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $id . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$id.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -43,7 +43,7 @@ trait TeamsBaseServer /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -62,15 +62,14 @@ trait TeamsBaseServer /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid . 'dasdasd', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'dasdasd', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -85,19 +84,19 @@ trait TeamsBaseServer { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid() . 'friend@localhost.test'; + $email = uniqid().'friend@localhost.test'; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -126,51 +125,50 @@ trait TeamsBaseServer /** * Test for FAILURE */ - - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(409, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => 'dasdkaskdjaskdjasjkd', 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => 'bad string', - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://example.com/join-us#title' // bad url + 'url' => 'http://example.com/join-us#title', // bad url ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -178,7 +176,7 @@ trait TeamsBaseServer return [ 'teamUid' => $teamUid, 'userUid' => $userUid, - 'membershipUid' => $membershipUid + 'membershipUid' => $membershipUid, ]; } @@ -194,12 +192,12 @@ trait TeamsBaseServer * Test for SUCCESS */ $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => $roles, ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -211,19 +209,18 @@ trait TeamsBaseServer $this->assertEquals($roles[1], $response['body']['roles'][1]); $this->assertEquals($roles[2], $response['body']['roles'][2]); - /** * Test for FAILURE */ $apiKey = $this->getNewKey(['teams.read']); $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $apiKey + 'x-appwrite-key' => $apiKey, ], [ - 'roles' => $roles + 'roles' => $roles, ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -240,7 +237,7 @@ trait TeamsBaseServer $userUid = $data['userUid'] ?? ''; /** Get Team Count */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -253,7 +250,7 @@ trait TeamsBaseServer $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); /** Delete User */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $userUid, array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$userUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -264,12 +261,11 @@ trait TeamsBaseServer sleep(5); /** Get Team Count */ - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEquals('Arsenal', $response['body']['name']); diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index e86c18a8e2..7c5a667bbc 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; @@ -22,10 +22,10 @@ class TeamsConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_POST, '/teams', \array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => 'console' + 'x-appwrite-project' => 'console', ], $this->getHeaders()), [ 'name' => 'Latest version Team', - 'teamId' => ID::unique() + 'teamId' => ID::unique(), ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -37,9 +37,9 @@ class TeamsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/teams', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'x-appwrite-response-format' => '0.11.0' + 'x-appwrite-response-format' => '0.11.0', ], $this->getHeaders()), [ - 'name' => 'Latest version Team' + 'name' => 'Latest version Team', // Notice "teamId' is not defined ]); @@ -49,14 +49,14 @@ class TeamsConsoleClientTest extends Scope /** * Cleanup, so I don't invalidate some listTeams requests by mistake */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team1Id, \array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team1Id, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team2Id, \array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team2Id, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); @@ -71,18 +71,18 @@ class TeamsConsoleClientTest extends Scope { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid() . 'friend@localhost.test'; + $email = uniqid().'friend@localhost.test'; $name = 'Friend User'; $password = 'password'; // Create a user account before we create a invite so we can check if the user has permissions when it shouldn't $user = $this->client->call(Client::METHOD_POST, '/account', [ 'content-type' => 'application/json', - 'x-appwrite-project' => 'console'], [ - 'userId' => 'unique()', - 'email' => $email, - 'password' => $password, - 'name' => $name, + 'x-appwrite-project' => 'console', ], [ + 'userId' => 'unique()', + 'email' => $email, + 'password' => $password, + 'name' => $name, ], false); $this->assertEquals(201, $user['headers']['status-code']); @@ -90,14 +90,14 @@ class TeamsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -108,7 +108,7 @@ class TeamsConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -117,7 +117,7 @@ class TeamsConsoleClientTest extends Scope $ownerMembershipUid = $response['body']['memberships'][1]['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsCustomClientTest.php b/tests/e2e/Services/Teams/TeamsCustomClientTest.php index 3b46cbcb7f..83a8080d1d 100644 --- a/tests/e2e/Services/Teams/TeamsCustomClientTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Teams; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; class TeamsCustomClientTest extends Scope diff --git a/tests/e2e/Services/Teams/TeamsCustomServerTest.php b/tests/e2e/Services/Teams/TeamsCustomServerTest.php index ccbb598934..325b5892fc 100644 --- a/tests/e2e/Services/Teams/TeamsCustomServerTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomServerTest.php @@ -5,7 +5,6 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use Tests\E2E\Client; class TeamsCustomServerTest extends Scope { diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index baf601789a..5842212e07 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -107,7 +107,7 @@ trait UsersBase 'email' => 'sha512@appwrite.io', 'password' => '4243da0a694e8a2f727c8060fe0507c8fa01ca68146c76d2c190805b638c20c6bf6ba04e21f11ae138785d0bff63c416e6f87badbffad37f6dee50094cc38c70', // appwrite (sha512) 'name' => 'SHA512 User', - 'passwordVersion' => 'sha512' + 'passwordVersion' => 'sha512', ]); $this->assertEquals($res['headers']['status-code'], 201); @@ -127,7 +127,7 @@ trait UsersBase 'passwordCpu' => 16384, 'passwordMemory' => 13, 'passwordParallel' => 2, - 'passwordLength' => 64 + 'passwordLength' => 64, ]); $this->assertEquals($res['headers']['status-code'], 201); @@ -191,7 +191,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $userId . '@appwrite.io', + 'email' => $userId.'@appwrite.io', 'password' => 'appwrite', ]); @@ -201,14 +201,14 @@ trait UsersBase foreach ($userIds as $userId) { // Ensure all passwords were re-hashed - $response = $this->client->call(Client::METHOD_GET, '/users/' . $userId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$userId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($userId, $response['body']['$id']); - $this->assertEquals($userId . '@appwrite.io', $response['body']['email']); + $this->assertEquals($userId.'@appwrite.io', $response['body']['email']); $this->assertEquals('argon2', $response['body']['hash']); $this->assertStringStartsWith('$argon2', $response['body']['password']); } @@ -220,7 +220,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $userId . '@appwrite.io', + 'email' => $userId.'@appwrite.io', 'password' => 'appwrite', ]); @@ -349,7 +349,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("name", "' . $user1['name'] . '")'] + 'queries' => ['equal("name", "'.$user1['name'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -362,7 +362,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("email", "' . $user1['email'] . '")'] + 'queries' => ['equal("email", "'.$user1['email'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -375,7 +375,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("status", true)'] + 'queries' => ['equal("status", true)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -391,7 +391,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("status", false)'] + 'queries' => ['equal("status", false)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -403,7 +403,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("passwordUpdate", "' . $user1['passwordUpdate'] . '")'] + 'queries' => ['equal("passwordUpdate", "'.$user1['passwordUpdate'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -416,7 +416,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("registration", "' . $user1['registration'] . '")'] + 'queries' => ['equal("registration", "'.$user1['registration'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -429,7 +429,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("emailVerification", false)'] + 'queries' => ['equal("emailVerification", false)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -445,7 +445,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("emailVerification", true)'] + 'queries' => ['equal("emailVerification", true)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -457,7 +457,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("phoneVerification", false)'] + 'queries' => ['equal("phoneVerification", false)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -469,7 +469,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("phoneVerification", true)'] + 'queries' => ['equal("phoneVerification", true)'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -481,7 +481,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("' . $data['userId'] . '")'] + 'queries' => ['cursorAfter("'.$data['userId'].'")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -494,7 +494,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("user1")'] + 'queries' => ['cursorBefore("user1")'], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -510,7 +510,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => "Ronaldo", + 'search' => 'Ronaldo', ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -522,7 +522,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => "cristiano.ronaldo@manchester-united.co.uk", + 'search' => 'cristiano.ronaldo@manchester-united.co.uk', ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -534,7 +534,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => "cristiano.ronaldo", + 'search' => 'cristiano.ronaldo', ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -546,7 +546,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => "manchester", + 'search' => 'manchester', ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -558,7 +558,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => "united.co.uk", + 'search' => 'united.co.uk', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -572,7 +572,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => "man", + 'search' => 'man', ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -602,7 +602,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("unknown")'] + 'queries' => ['cursorAfter("unknown")'], ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -616,7 +616,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -627,7 +627,7 @@ trait UsersBase $this->assertEquals($user['body']['status'], true); $this->assertGreaterThan('2000-01-01 00:00:00', $user['body']['registration']); - $sessions = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/sessions', array_merge([ + $sessions = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -670,7 +670,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/name', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/name', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -680,7 +680,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['name'], 'Updated name'); - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -737,7 +737,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/email', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -747,7 +747,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['email'], 'users.service@updated.com'); - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -804,7 +804,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/password', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/password', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -819,7 +819,7 @@ trait UsersBase 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'email' => 'users.service@updated.com', - 'password' => 'password2' + 'password' => 'password2', ]); $this->assertEquals($session['headers']['status-code'], 201); @@ -836,7 +836,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/status', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/status', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -846,7 +846,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['status'], false); - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -865,7 +865,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/verification', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/verification', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -875,7 +875,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['emailVerification'], true); - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -895,7 +895,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -909,7 +909,7 @@ trait UsersBase $this->assertEquals($user['body']['funcKey1'], 'funcValue1'); $this->assertEquals($user['body']['funcKey2'], 'funcValue2'); - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -923,7 +923,7 @@ trait UsersBase /** * Test for FAILURE */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -932,7 +932,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 400); - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -950,8 +950,8 @@ trait UsersBase /** * Test for SUCCESS */ - $updatedNumber = "+910000000000"; //dummy number - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/phone', array_merge([ + $updatedNumber = '+910000000000'; //dummy number + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/phone', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -961,7 +961,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['phone'], $updatedNumber); - $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -972,13 +972,12 @@ trait UsersBase /** * Test for FAILURE */ - - $errorType = "user_phone_already_exists"; - $user1Id = "user1"; + $errorType = 'user_phone_already_exists'; + $user1Id = 'user1'; $statusCodeForUserPhoneAlredyExists = 409; // adding same number ($updatedNumber) to different user i.e user1 - $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $user1Id . '/phone', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$user1Id.'/phone', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -997,7 +996,7 @@ trait UsersBase public function testUpdateUserNumberSearch($data): void { $id = $data['userId'] ?? ''; - $newNumber = "+910000000000"; //dummy number + $newNumber = '+910000000000'; //dummy number /** * Test for SUCCESS @@ -1067,7 +1066,7 @@ trait UsersBase */ public function testUpdateUserLabels(array $labels, int $expectedStatus, array $expectedLabels, array $data): array { - $user = $this->client->call(Client::METHOD_PUT, '/users/' . $data['userId'] . '/labels', array_merge([ + $user = $this->client->call(Client::METHOD_PUT, '/users/'.$data['userId'].'/labels', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1087,7 +1086,7 @@ trait UsersBase */ public function testUpdateUserLabelsWithoutLabels(array $data): array { - $user = $this->client->call(Client::METHOD_PUT, '/users/' . $data['userId'] . '/labels', array_merge([ + $user = $this->client->call(Client::METHOD_PUT, '/users/'.$data['userId'].'/labels', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -1109,7 +1108,6 @@ trait UsersBase $this->assertEquals(Response::STATUS_CODE_NOT_FOUND, $user['headers']['status-code']); } - /** * @depends testGetUser */ @@ -1118,7 +1116,7 @@ trait UsersBase /** * Test for SUCCESS */ - $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1127,7 +1125,7 @@ trait UsersBase $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1139,7 +1137,7 @@ trait UsersBase $this->assertLessThanOrEqual(1, count($logs['body']['logs'])); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1150,7 +1148,7 @@ trait UsersBase $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1165,47 +1163,47 @@ trait UsersBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(-1)'] + 'queries' => ['limit(-1)'], ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(-1)'] + 'queries' => ['offset(-1)'], ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("$id", "asdf")'] + 'queries' => ['equal("$id", "asdf")'], ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['orderAsc("$id")'] + 'queries' => ['orderAsc("$id")'], ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAsc("$id")'] + 'queries' => ['cursorAsc("$id")'], ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -1219,7 +1217,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1229,7 +1227,7 @@ trait UsersBase /** * Test for FAILURE */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Users/UsersConsoleClientTest.php b/tests/e2e/Services/Users/UsersConsoleClientTest.php index 8943bfab63..cc44520387 100644 --- a/tests/e2e/Services/Users/UsersConsoleClientTest.php +++ b/tests/e2e/Services/Users/UsersConsoleClientTest.php @@ -2,9 +2,9 @@ namespace Tests\E2E\Services\Users; -use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; class UsersConsoleClientTest extends Scope @@ -17,10 +17,9 @@ class UsersConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/users/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'range' => '32h', ]); @@ -32,7 +31,7 @@ class UsersConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_GET, '/users/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'] + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'range' => '24h', ]); diff --git a/tests/e2e/Services/Users/UsersCustomServerTest.php b/tests/e2e/Services/Users/UsersCustomServerTest.php index 6b9a990d4c..2442f1bf7d 100644 --- a/tests/e2e/Services/Users/UsersCustomServerTest.php +++ b/tests/e2e/Services/Users/UsersCustomServerTest.php @@ -2,7 +2,6 @@ namespace Tests\E2E\Services\Users; -use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index 6e30e7abc1..663167e38b 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -5,7 +5,6 @@ namespace Tests\E2E\Services\Webhooks; use Appwrite\Tests\Retry; use CURLFile; use Tests\E2E\Client; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -16,10 +15,10 @@ trait WebhooksBase public static function getWebhookSignature(array $webhook, string $signatureKey): string { $payload = json_encode($webhook['data']); - $url = $webhook['url']; - return base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); - } + $url = $webhook['url']; + return base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + } public function testCreateCollection(): array { @@ -27,23 +26,23 @@ trait WebhooksBase * Create database */ $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'databaseId' => ID::unique(), - 'name' => 'Actors DB', + 'databaseId' => ID::unique(), + 'name' => 'Actors DB', ]); $databaseId = $database['body']['$id']; - /** + /** * Test for SUCCESS */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -67,8 +66,8 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); @@ -91,30 +90,30 @@ trait WebhooksBase $actorsId = $data['actorsId']; $databaseId = $data['databaseId']; - $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ + $firstName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'firstName', 'size' => 256, 'required' => true, ]); - $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ + $lastName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'lastName', 'size' => 256, 'required' => true, ]); - $extra = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ + $extra = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'extra', 'size' => 64, @@ -139,9 +138,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -151,10 +150,10 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['key']); $this->assertEquals($webhook['data']['key'], 'extra'); - $removed = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/attributes/' . $extra['body']['key'], array_merge([ + $removed = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/attributes/'.$extra['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals(204, $removed['headers']['status-code']); @@ -165,9 +164,9 @@ trait WebhooksBase // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -191,7 +190,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -218,9 +217,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -254,7 +253,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $data['documentId'], array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$data['documentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -280,9 +279,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -315,7 +314,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -337,7 +336,7 @@ trait WebhooksBase $this->assertEquals($document['headers']['status-code'], 201); $this->assertNotEmpty($document['body']['$id']); - $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $document['body']['$id'], array_merge([ + $document = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -350,9 +349,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -373,7 +372,6 @@ trait WebhooksBase return $data; } - public function testCreateStorageBucket(): array { /** @@ -382,7 +380,7 @@ trait WebhooksBase $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'bucketId' => ID::unique(), 'name' => 'Test Bucket', @@ -431,10 +429,10 @@ trait WebhooksBase /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'], array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test Bucket Updated', 'fileSecurity' => true, @@ -474,10 +472,10 @@ trait WebhooksBase $bucketId = $data['bucketId']; //enable bucket - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'], array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Test Bucket Updated', 'fileSecurity' => true, @@ -488,12 +486,12 @@ trait WebhooksBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -551,7 +549,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -607,7 +605,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -655,10 +653,10 @@ trait WebhooksBase /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId, array_merge([ + $bucket = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals($bucket['headers']['status-code'], 204); @@ -694,7 +692,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal' + 'name' => 'Arsenal', ]); $teamId = $team['body']['$id']; @@ -737,11 +735,11 @@ trait WebhooksBase /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId, array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'name' => 'Demo New' + 'name' => 'Demo New', ]); $this->assertEquals(200, $team['headers']['status-code']); @@ -780,14 +778,14 @@ trait WebhooksBase { $id = $data['teamId'] ?? ''; - $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $id . '/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$id.'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ] + ], ]); $this->assertEquals($team['headers']['status-code'], 200); @@ -796,8 +794,8 @@ trait WebhooksBase $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -830,7 +828,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Chelsea' + 'name' => 'Chelsea', ]); $teamId = $team['body']['$id']; @@ -838,7 +836,7 @@ trait WebhooksBase $this->assertEquals(201, $team['headers']['status-code']); $this->assertNotEmpty($team['body']['$id']); - $team = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team['body']['$id'], array_merge([ + $team = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -875,19 +873,19 @@ trait WebhooksBase public function testCreateTeamMembership($data): array { $teamId = $data['teamId'] ?? ''; - $email = uniqid() . 'friend@localhost.test'; + $email = uniqid().'friend@localhost.test'; /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_POST, '/teams/' . $teamId . '/memberships', array_merge([ + $team = $this->client->call(Client::METHOD_POST, '/teams/'.$teamId.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $this->assertEquals(201, $team['headers']['status-code']); @@ -942,19 +940,19 @@ trait WebhooksBase public function testDeleteTeamMembership($data): void { $teamId = $data['teamId'] ?? ''; - $email = uniqid() . 'friend@localhost.test'; + $email = uniqid().'friend@localhost.test'; /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_POST, '/teams/' . $teamId . '/memberships', array_merge([ + $team = $this->client->call(Client::METHOD_POST, '/teams/'.$teamId.'/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title' + 'url' => 'http://localhost:5000/join-us#title', ]); $membershipId = $team['body']['$id'] ?? ''; @@ -962,7 +960,7 @@ trait WebhooksBase $this->assertEquals(201, $team['headers']['status-code']); $this->assertNotEmpty($team['body']['$id']); - $team = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamId . '/memberships/' . $team['body']['$id'], array_merge([ + $team = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamId.'/memberships/'.$team['body']['$id'], array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php index 67c2dec36b..48f33a24e5 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -4,10 +4,9 @@ namespace Tests\E2E\Services\Webhooks; use Appwrite\Tests\Retry; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -19,7 +18,7 @@ class WebhooksCustomClientTest extends Scope public function testCreateAccount(): array { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -45,8 +44,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -77,7 +76,7 @@ class WebhooksCustomClientTest extends Scope public function testDeleteAccount(): array { - $email = uniqid() . 'user1@localhost.test'; + $email = uniqid().'user1@localhost.test'; $password = 'password'; $name = 'User Name 1'; @@ -107,13 +106,13 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 201); $id = $account['body']['$id']; - $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $account = $this->client->call(Client::METHOD_PATCH, '/account/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($account['headers']['status-code'], 200); @@ -121,8 +120,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -170,13 +169,13 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 201); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -248,15 +247,15 @@ class WebhooksCustomClientTest extends Scope ]); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertEquals($accountSession['headers']['status-code'], 201); - $accountSession = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionId, array_merge([ + $accountSession = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($accountSession['headers']['status-code'], 204); @@ -264,8 +263,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -334,7 +333,7 @@ class WebhooksCustomClientTest extends Scope ]); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertEquals($accountSession['headers']['status-code'], 201); @@ -342,7 +341,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ])); $this->assertEquals($accountSession['headers']['status-code'], 204); @@ -350,8 +349,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -407,7 +406,7 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 201); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; return array_merge($data, [ 'sessionId' => $sessionId, @@ -430,9 +429,9 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ - 'name' => $newName + 'name' => $newName, ]); $this->assertEquals($account['headers']['status-code'], 200); @@ -441,9 +440,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); - + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -483,7 +481,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -495,8 +493,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -531,14 +529,14 @@ class WebhooksCustomClientTest extends Scope { $id = $data['id'] ?? ''; $email = $data['email'] ?? ''; - $newEmail = uniqid() . 'new@localhost.test'; + $newEmail = uniqid().'new@localhost.test'; $session = $data['session'] ?? ''; $account = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'email' => $newEmail, 'password' => 'new-password', @@ -550,8 +548,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -592,12 +590,12 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ] + ], ]); $this->assertEquals($account['headers']['status-code'], 200); @@ -606,8 +604,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -661,8 +659,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -721,8 +719,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -764,7 +762,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'url' => 'http://localhost/verification', ]); @@ -777,8 +775,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -821,7 +819,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, ]), [ 'userId' => $id, 'secret' => $secret, @@ -835,8 +833,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -878,7 +876,7 @@ class WebhooksCustomClientTest extends Scope /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ + $team = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -893,8 +891,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index 02c3a2dbfd..836c81822b 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -8,7 +8,6 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\CLI\Console; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -31,10 +30,10 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $actors = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $id, array_merge([ + $actors = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'name' => 'Actors1', 'documentSecurity' => true, @@ -49,8 +48,8 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); @@ -73,10 +72,10 @@ class WebhooksCustomServerTest extends Scope $actorsId = $data['actorsId']; $databaseId = $data['databaseId']; - $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'key' => 'fullname', 'type' => 'key', @@ -97,9 +96,9 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -109,10 +108,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); // Remove index - $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/indexes/' . $index['body']['key'], array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/indexes/'.$index['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ])); // // wait for database worker to remove index @@ -122,9 +121,9 @@ class WebhooksCustomServerTest extends Scope // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -144,7 +143,7 @@ class WebhooksCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders()), [ 'databaseId' => ID::unique(), 'name' => 'Actors DB', @@ -155,10 +154,10 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'collectionId' => ID::unique(), 'name' => 'Demo', @@ -176,10 +175,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($actors['headers']['status-code'], 201); $this->assertNotEmpty($actors['body']['$id']); - $actors = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ + $actors = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] + 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); $this->assertEquals($actors['headers']['status-code'], 204); @@ -190,8 +189,8 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); @@ -208,7 +207,7 @@ class WebhooksCustomServerTest extends Scope public function testCreateUser(): array { - $email = uniqid() . 'user@localhost.test'; + $email = uniqid().'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -268,11 +267,11 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $id . '/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$id.'/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'prefs' => ['a' => 'b'] + 'prefs' => ['a' => 'b'], ]); $this->assertEquals($user['headers']['status-code'], 200); @@ -309,7 +308,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/status', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/status', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -356,7 +355,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -442,7 +441,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -451,14 +450,14 @@ class WebhooksCustomServerTest extends Scope 'execute' => [Role::any()->toString()], 'vars' => [ 'key1' => 'value1', - ] + ], ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertEquals($function['body']['$id'], $data['functionId']); // Create variable - $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -496,16 +495,16 @@ class WebhooksCustomServerTest extends Scope $stderr = ''; $stdout = ''; $folder = 'timeout'; - $code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz"; - Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); + $code = realpath(__DIR__.'/../../../resources/functions')."/{$folder}/code.tar.gz"; + Console::execute('cd '.realpath(__DIR__.'/../../../resources/functions')."/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true + 'activate' => true, ]); $id = $data['functionId'] ?? ''; @@ -546,7 +545,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $id . '/deployments/' . $deploymentId, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$id.'/deployments/'.$deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -594,11 +593,11 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $id . '/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$id.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'async' => true + 'async' => true, ]); $executionId = $execution['body']['$id'] ?? ''; @@ -665,7 +664,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $id . '/deployments/' . $deploymentId, array_merge([ + $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/'.$id.'/deployments/'.$deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -710,7 +709,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $id, array_merge([ + $function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/extensions/Retryable.php b/tests/extensions/Retryable.php index 61fec0ef12..aa85d22eae 100644 --- a/tests/extensions/Retryable.php +++ b/tests/extensions/Retryable.php @@ -14,6 +14,7 @@ trait Retryable * accounting for any retries configured by the {@see Retry} annotation. * * @return void + * * @throws \ReflectionException * @throws \Throwable */ @@ -21,14 +22,15 @@ trait Retryable { $retries = $this->getNumberOfRetries(); $ex = null; - for ($i = 0; $i <= $retries; ++$i) { + for ($i = 0; $i <= $retries; $i++) { try { parent::runBare(); + return; - } catch (\Throwable | \Exception $ex) { + } catch (\Throwable|\Exception $ex) { // Swallow the exception until we have exhausted our retries. if ($i !== $retries) { - echo 'Flaky test failed, retrying...' . PHP_EOL; + echo 'Flaky test failed, retrying...'.PHP_EOL; } } } @@ -39,6 +41,7 @@ trait Retryable /** * @return int + * * @throws \ReflectionException */ private function getNumberOfRetries(): int @@ -53,11 +56,12 @@ trait Retryable $attribute = $attributes[0] ?? null; $args = $attribute?->getArguments(); $retries = $args['count'] ?? 0; + return \max(0, $retries); } /** - * @param \ReflectionClass $reflection + * @param \ReflectionClass $reflection * @return \ReflectionClass */ private function getTestCaseRoot(\ReflectionClass $reflection): \ReflectionClass @@ -65,6 +69,7 @@ trait Retryable if ($reflection->getName() === TestCase::class) { return $reflection; } + return $this->getTestCaseRoot($reflection->getParentClass()); } } diff --git a/tests/extensions/TestHook.php b/tests/extensions/TestHook.php index 67c1215c4c..f6db16a227 100644 --- a/tests/extensions/TestHook.php +++ b/tests/extensions/TestHook.php @@ -3,11 +3,11 @@ namespace Appwrite\Tests; use PHPUnit\Runner\AfterTestHook; -use Exception; class TestHook implements AfterTestHook { protected const MAX_SECONDS_ALLOWED = 15; + public function executeAfterTest(string $test, float $time): void { printf( diff --git a/tests/resources/functions/php-fn/index.php b/tests/resources/functions/php-fn/index.php index 7947c4a6a6..6da31cd499 100644 --- a/tests/resources/functions/php-fn/index.php +++ b/tests/resources/functions/php-fn/index.php @@ -1,7 +1,7 @@ json([ 'APPWRITE_FUNCTION_ID' => $request['variables']['APPWRITE_FUNCTION_ID'], diff --git a/tests/resources/functions/php-large/index.php b/tests/resources/functions/php-large/index.php index 84b6a991fe..83140c27ff 100644 --- a/tests/resources/functions/php-large/index.php +++ b/tests/resources/functions/php-large/index.php @@ -10,6 +10,6 @@ return function ($request, $response) { 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request['variables']['APPWRITE_FUNCTION_RUNTIME_VERSION'], 'APPWRITE_FUNCTION_EVENT' => $request['variables']['APPWRITE_FUNCTION_EVENT'], 'APPWRITE_FUNCTION_EVENT_DATA' => $request['variables']['APPWRITE_FUNCTION_EVENT_DATA'], - 'UNICODE_TEST' => "êä" + 'UNICODE_TEST' => 'êä', ]); }; diff --git a/tests/resources/functions/php/index.php b/tests/resources/functions/php/index.php index 84b6a991fe..83140c27ff 100644 --- a/tests/resources/functions/php/index.php +++ b/tests/resources/functions/php/index.php @@ -10,6 +10,6 @@ return function ($request, $response) { 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request['variables']['APPWRITE_FUNCTION_RUNTIME_VERSION'], 'APPWRITE_FUNCTION_EVENT' => $request['variables']['APPWRITE_FUNCTION_EVENT'], 'APPWRITE_FUNCTION_EVENT_DATA' => $request['variables']['APPWRITE_FUNCTION_EVENT_DATA'], - 'UNICODE_TEST' => "êä" + 'UNICODE_TEST' => 'êä', ]); }; diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 3e6a760b25..a3aa78bc6d 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -3,12 +3,12 @@ namespace Tests\Unit\Auth; use Appwrite\Auth\Auth; +use PHPUnit\Framework\TestCase; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use PHPUnit\Framework\TestCase; use Utopia\Database\Validator\Roles; class AuthTest extends TestCase @@ -127,13 +127,13 @@ class AuthTest extends TestCase // Scrypt $plain = 'some-scrypt-password'; $hash = 'b448ad7ba88b653b5b56b8053a06806724932d0751988bc9cd0ef7ff059e8ba8a020e1913b7069a650d3f99a1559aba0221f2c277826919513a054e76e339028'; - $generatedHash = Auth::passwordHash($plain, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2]); + $generatedHash = Auth::passwordHash($plain, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2]); - $this->assertEquals(true, Auth::passwordVerify($plain, $generatedHash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); - $this->assertEquals(true, Auth::passwordVerify($plain, $hash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); - $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', [ 'salt' => 'some-wrong-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); - $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 10, 'costParallel' => 2])); - $this->assertEquals(false, Auth::passwordVerify('wrongPassword', $hash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(true, Auth::passwordVerify($plain, $generatedHash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(true, Auth::passwordVerify($plain, $hash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', ['salt' => 'some-wrong-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 10, 'costParallel' => 2])); + $this->assertEquals(false, Auth::passwordVerify('wrongPassword', $hash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); // ScryptModified tested are in provider-specific tests below @@ -164,7 +164,7 @@ class AuthTest extends TestCase $saltSeparator = 'Bw=='; $signerKey = 'XyEKE9RcTDeLEsL/RjwPDBv/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ=='; - $options = [ 'salt' => $salt, 'saltSeparator' => $saltSeparator, 'signerKey' => $signerKey ]; + $options = ['salt' => $salt, 'saltSeparator' => $saltSeparator, 'signerKey' => $signerKey]; $generatedHash = Auth::passwordHash($plain, 'scryptMod', $options); $this->assertEquals(true, Auth::passwordVerify($plain, $generatedHash, 'scryptMod', $options)); $this->assertEquals(true, Auth::passwordVerify($plain, $hash, 'scryptMod', $options)); @@ -339,7 +339,7 @@ class AuthTest extends TestCase public function testGuestRoles(): void { $user = new Document([ - '$id' => '' + '$id' => '', ]); $roles = Auth::getRoles($user); @@ -349,11 +349,11 @@ class AuthTest extends TestCase public function testUserRoles(): void { - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'labels' => [ 'vip', - 'admin' + 'admin', ], 'emailVerification' => true, 'phoneVerification' => true, @@ -364,18 +364,18 @@ class AuthTest extends TestCase 'confirm' => true, 'roles' => [ 'administrator', - 'moderator' - ] + 'moderator', + ], ], [ '$id' => ID::custom('abc'), 'teamId' => ID::custom('def'), 'confirm' => true, 'roles' => [ - 'guest' - ] - ] - ] + 'guest', + ], + ], + ], ]); $roles = Auth::getRoles($user); @@ -414,7 +414,7 @@ class AuthTest extends TestCase public function testPrivilegedUserRoles(): void { Authorization::setRole(Auth::USER_ROLE_OWNER); - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'emailVerification' => true, 'phoneVerification' => true, @@ -425,18 +425,18 @@ class AuthTest extends TestCase 'confirm' => true, 'roles' => [ 'administrator', - 'moderator' - ] + 'moderator', + ], ], [ '$id' => ID::custom('abc'), 'teamId' => ID::custom('def'), 'confirm' => true, 'roles' => [ - 'guest' - ] - ] - ] + 'guest', + ], + ], + ], ]); $roles = Auth::getRoles($user); @@ -458,7 +458,7 @@ class AuthTest extends TestCase public function testAppUserRoles(): void { Authorization::setRole(Auth::USER_ROLE_APPS); - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'memberships' => [ [ @@ -467,18 +467,18 @@ class AuthTest extends TestCase 'confirm' => true, 'roles' => [ 'administrator', - 'moderator' - ] + 'moderator', + ], ], [ '$id' => ID::custom('abc'), 'teamId' => ID::custom('def'), 'confirm' => true, 'roles' => [ - 'guest' - ] - ] - ] + 'guest', + ], + ], + ], ]); $roles = Auth::getRoles($user); diff --git a/tests/unit/Auth/Validator/PasswordDictionaryTest.php b/tests/unit/Auth/Validator/PasswordDictionaryTest.php index fd7f51ff16..283d5c79fa 100644 --- a/tests/unit/Auth/Validator/PasswordDictionaryTest.php +++ b/tests/unit/Auth/Validator/PasswordDictionaryTest.php @@ -4,7 +4,6 @@ namespace Tests\Unit\Auth\Validator; use Appwrite\Auth\Validator\PasswordDictionary; use PHPUnit\Framework\TestCase; -use Utopia\Database\Document; class PasswordDictionaryTest extends TestCase { diff --git a/tests/unit/Docker/ComposeTest.php b/tests/unit/Docker/ComposeTest.php index 56448ffd01..350b41a820 100644 --- a/tests/unit/Docker/ComposeTest.php +++ b/tests/unit/Docker/ComposeTest.php @@ -12,7 +12,7 @@ class ComposeTest extends TestCase public function setUp(): void { - $data = @file_get_contents(__DIR__ . '/../../resources/docker/docker-compose.yml'); + $data = @file_get_contents(__DIR__.'/../../resources/docker/docker-compose.yml'); if ($data === false) { throw new Exception('Failed to read compose file'); diff --git a/tests/unit/Docker/EnvTest.php b/tests/unit/Docker/EnvTest.php index e6c9b8cadf..b271bde504 100644 --- a/tests/unit/Docker/EnvTest.php +++ b/tests/unit/Docker/EnvTest.php @@ -12,7 +12,7 @@ class EnvTest extends TestCase public function setUp(): void { - $data = @file_get_contents(__DIR__ . '/../../resources/docker/.env'); + $data = @file_get_contents(__DIR__.'/../../resources/docker/.env'); if ($data === false) { throw new Exception('Failed to read compose file'); @@ -34,10 +34,10 @@ class EnvTest extends TestCase public function testExport(): void { - $this->assertEquals("_APP_X=value1 + $this->assertEquals('_APP_X=value1 _APP_Y=value2 _APP_Z=value3 _APP_W=value5= -", $this->object->export()); +', $this->object->export()); } } diff --git a/tests/unit/Event/EventTest.php b/tests/unit/Event/EventTest.php index a328c8d599..13f2bb4fd2 100644 --- a/tests/unit/Event/EventTest.php +++ b/tests/unit/Event/EventTest.php @@ -10,15 +10,16 @@ use Utopia\App; class EventTest extends TestCase { protected ?Event $object = null; + protected string $queue = ''; public function setUp(): void { $redisHost = App::getEnv('_APP_REDIS_HOST', ''); $redisPort = App::getEnv('_APP_REDIS_PORT', ''); - \Resque::setBackend($redisHost . ':' . $redisPort); + \Resque::setBackend($redisHost.':'.$redisPort); - $this->queue = 'v1-tests' . uniqid(); + $this->queue = 'v1-tests'.uniqid(); $this->object = new Event($this->queue, 'TestsV1'); } @@ -85,7 +86,7 @@ class EventTest extends TestCase public function testGenerateEvents(): void { $event = Event::generateEvents('users.[userId].create', [ - 'userId' => 'torsten' + 'userId' => 'torsten', ]); $this->assertCount(4, $event); $this->assertContains('users.torsten.create', $event); @@ -94,7 +95,7 @@ class EventTest extends TestCase $this->assertContains('users.*', $event); $event = Event::generateEvents('users.[userId].update.email', [ - 'userId' => 'torsten' + 'userId' => 'torsten', ]); $this->assertCount(6, $event); $this->assertContains('users.torsten.update.email', $event); @@ -151,10 +152,9 @@ class EventTest extends TestCase $this->assertContains('databases.chaptersDB.collections.*.documents.*', $event); $this->assertContains('databases.chaptersDB.collections.*.documents.*.create', $event); - try { $event = Event::generateEvents('collections.[collectionId].documents.[documentId].create', [ - 'collectionId' => 'chapters' + 'collectionId' => 'chapters', ]); $this->fail(); } catch (\Throwable $th) { diff --git a/tests/unit/General/CollectionsTest.php b/tests/unit/General/CollectionsTest.php index 73a9ccd0c2..8596b857a8 100644 --- a/tests/unit/General/CollectionsTest.php +++ b/tests/unit/General/CollectionsTest.php @@ -10,7 +10,7 @@ class CollectionsTest extends TestCase public function setUp(): void { - $this->collections = require('app/config/collections.php'); + $this->collections = require 'app/config/collections.php'; } public function testDuplicateRules(): void diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 6fe7dda71f..14ec84a8e6 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -3,9 +3,9 @@ namespace Tests\Unit\Messaging; use Appwrite\Auth\Auth; -use Utopia\Database\Document; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -17,10 +17,15 @@ class MessagingChannelsTest extends TestCase public $connectionsPerChannel = 10; public Realtime $realtime; + public $connectionsCount = 0; + public $connectionsAuthenticated = 0; + public $connectionsGuest = 0; + public $connectionsTotal = 0; + public $allChannels = [ 'files', 'files.1', @@ -51,19 +56,19 @@ class MessagingChannelsTest extends TestCase for ($i = 0; $i < $this->connectionsPerChannel; $i++) { foreach ($this->allChannels as $index => $channel) { $user = new Document([ - '$id' => ID::custom('user' . $this->connectionsCount), + '$id' => ID::custom('user'.$this->connectionsCount), 'memberships' => [ [ - '$id' => ID::custom('member' . $i), - 'teamId' => ID::custom('team' . $i), + '$id' => ID::custom('member'.$i), + 'teamId' => ID::custom('team'.$i), 'confirm' => true, 'roles' => [ empty($index % 2) ? Auth::USER_ROLE_ADMIN : 'member', - ] - ] - ] + ], + ], + ], ]); $roles = Auth::getRoles($user); @@ -87,7 +92,7 @@ class MessagingChannelsTest extends TestCase for ($i = 0; $i < $this->connectionsPerChannel; $i++) { foreach ($this->allChannels as $index => $channel) { $user = new Document([ - '$id' => '' + '$id' => '', ]); $roles = Auth::getRoles($user); @@ -170,8 +175,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ] - ] + ], + ], ]; $receivers = $this->realtime->getSubscribers($event); @@ -194,7 +199,7 @@ class MessagingChannelsTest extends TestCase { $roles = [ Role::guests()->toString(), - Role::users()->toString() + Role::users()->toString(), ]; foreach ($this->allChannels as $index => $channel) { foreach ($roles as $role) { @@ -206,8 +211,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ] - ] + ], + ], ]; $receivers = $this->realtime->getSubscribers($event); @@ -232,7 +237,7 @@ class MessagingChannelsTest extends TestCase foreach ($this->allChannels as $index => $channel) { $permissions = []; for ($i = 0; $i < $this->connectionsPerChannel; $i++) { - $permissions[] = Role::user(ID::custom('user' . (!empty($i) ? $i : '') . $index))->toString(); + $permissions[] = Role::user(ID::custom('user'.(! empty($i) ? $i : '').$index))->toString(); } $event = [ 'project' => '1', @@ -240,8 +245,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ] - ] + ], + ], ]; $receivers = $this->realtime->getSubscribers($event); @@ -266,8 +271,8 @@ class MessagingChannelsTest extends TestCase $permissions = []; for ($i = 0; $i < $this->connectionsPerChannel; $i++) { - $permissions[] = Role::team(ID::custom('team' . $i))->toString(); - $permissions[] = Role::member(ID::custom('member' . $i))->toString(); + $permissions[] = Role::team(ID::custom('team'.$i))->toString(); + $permissions[] = Role::member(ID::custom('member'.$i))->toString(); } $event = [ 'project' => '1', @@ -275,8 +280,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ] - ] + ], + ], ]; $receivers = $this->realtime->getSubscribers($event); @@ -298,8 +303,8 @@ class MessagingChannelsTest extends TestCase : 'member'; $permissions = [ - Role::team(ID::custom('team' . $index), $role)->toString(), - Role::member(ID::custom('member' . $index))->toString() + Role::team(ID::custom('team'.$index), $role)->toString(), + Role::member(ID::custom('member'.$index))->toString(), ]; $event = [ @@ -308,8 +313,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ] - ] + ], + ], ]; $receivers = $this->realtime->getSubscribers($event); diff --git a/tests/unit/Messaging/MessagingGuestTest.php b/tests/unit/Messaging/MessagingGuestTest.php index 1aaa1febca..660e9519e3 100644 --- a/tests/unit/Messaging/MessagingGuestTest.php +++ b/tests/unit/Messaging/MessagingGuestTest.php @@ -27,8 +27,8 @@ class MessagingGuestTest extends TestCase 'channels' => [ 0 => 'documents', 1 => 'documents', - ] - ] + ], + ], ]; $receivers = $realtime->getSubscribers($event); diff --git a/tests/unit/Messaging/MessagingTest.php b/tests/unit/Messaging/MessagingTest.php index c2e3971945..d6ae6b095b 100644 --- a/tests/unit/Messaging/MessagingTest.php +++ b/tests/unit/Messaging/MessagingTest.php @@ -2,9 +2,9 @@ namespace Tests\Unit\Messaging; -use Utopia\Database\Document; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -44,8 +44,8 @@ class MessagingTest extends TestCase 'data' => [ 'channels' => [ 0 => 'account.123', - ] - ] + ], + ], ]; $receivers = $realtime->getSubscribers($event); @@ -148,7 +148,7 @@ class MessagingTest extends TestCase public function testConvertChannelsGuest(): void { $user = new Document([ - '$id' => '' + '$id' => '', ]); $channels = [ @@ -156,7 +156,7 @@ class MessagingTest extends TestCase 1 => 'documents', 2 => 'documents.789', 3 => 'account', - 4 => 'account.456' + 4 => 'account.456', ]; $channels = Realtime::convertChannels($channels, $user->getId()); @@ -170,30 +170,30 @@ class MessagingTest extends TestCase public function testConvertChannelsUser(): void { - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'memberships' => [ [ 'teamId' => ID::custom('abc'), 'roles' => [ 'administrator', - 'moderator' - ] + 'moderator', + ], ], [ 'teamId' => ID::custom('def'), 'roles' => [ - 'guest' - ] - ] - ] + 'guest', + ], + ], + ], ]); $channels = [ 0 => 'files', 1 => 'documents', 2 => 'documents.789', 3 => 'account', - 4 => 'account.456' + 4 => 'account.456', ]; $channels = Realtime::convertChannels($channels, $user->getId()); @@ -321,7 +321,7 @@ class MessagingTest extends TestCase Permission::update(Role::team('123abc')), Permission::delete(Role::team('123abc')), ], - 'fileSecurity' => true + 'fileSecurity' => true, ]) ); diff --git a/tests/unit/Migration/MigrationTest.php b/tests/unit/Migration/MigrationTest.php index 13f9b9a3f5..c322cc9635 100644 --- a/tests/unit/Migration/MigrationTest.php +++ b/tests/unit/Migration/MigrationTest.php @@ -22,12 +22,12 @@ abstract class MigrationTest extends TestCase /** * Runs every document fix twice, to prevent corrupted data on multiple migrations. * - * @param Document $document + * @param Document $document */ protected function fixDocument(Document $document) { return $this->method->invokeArgs($this->migration, [ - $this->method->invokeArgs($this->migration, [$document]) + $this->method->invokeArgs($this->migration, [$document]), ]); } @@ -36,14 +36,14 @@ abstract class MigrationTest extends TestCase */ public function testMigrationVersions(): void { - require_once __DIR__ . '/../../../app/init.php'; + require_once __DIR__.'/../../../app/init.php'; foreach (Migration::$versions as $class) { - $this->assertTrue(class_exists('Appwrite\\Migration\\Version\\' . $class)); + $this->assertTrue(class_exists('Appwrite\\Migration\\Version\\'.$class)); } // Test if current version exists // Only test official releases - skip if latest is release candidate - if (!(\str_contains(APP_VERSION_STABLE, 'RC'))) { + if (! (\str_contains(APP_VERSION_STABLE, 'RC'))) { $this->assertArrayHasKey(APP_VERSION_STABLE, Migration::$versions); } } @@ -60,8 +60,8 @@ abstract class MigrationTest extends TestCase 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'] - ] + 'd' => ['a', 'b', 'c'], + ], ], [ 'bool' => true, 'string' => 'abc', @@ -71,8 +71,8 @@ abstract class MigrationTest extends TestCase 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'] - ] + 'd' => ['a', 'b', 'c'], + ], ])); $this->assertFalse(Migration::hasDifference([ 'bool' => true, @@ -83,15 +83,15 @@ abstract class MigrationTest extends TestCase 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'] - ] + 'd' => ['a', 'b', 'c'], + ], ], [ 'string' => 'abc', 'assoc' => [ 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'] + 'd' => ['a', 'b', 'c'], ], 'int' => 123, 'array' => ['a', 'b', 'c'], @@ -99,40 +99,40 @@ abstract class MigrationTest extends TestCase ])); $this->assertTrue(Migration::hasDifference([ - 'a' => true + 'a' => true, ], [ - 'b' => true + 'b' => true, ])); $this->assertTrue(Migration::hasDifference([ - 'a' => 'true' + 'a' => 'true', ], [ - 'a' => true + 'a' => true, ])); $this->assertTrue(Migration::hasDifference([ - 'a' => true + 'a' => true, ], [ - 'a' => false + 'a' => false, ])); $this->assertTrue(Migration::hasDifference([ 'nested' => [ - 'a' => true - ] + 'a' => true, + ], ], [ - 'nested' => [] + 'nested' => [], ])); $this->assertTrue(Migration::hasDifference([ 'assoc' => [ 'bool' => true, 'string' => 'abc', 'int' => 123, - 'array' => ['a', 'b', 'c'] - ] + 'array' => ['a', 'b', 'c'], + ], ], [ 'nested' => [ 'a' => true, 'int' => '123', - 'array' => ['a', 'b', 'c'] - ] + 'array' => ['a', 'b', 'c'], + ], ])); } } diff --git a/tests/unit/Network/Validators/EmailTest.php b/tests/unit/Network/Validators/EmailTest.php index f629ed6ddc..d74f2c30fc 100755 --- a/tests/unit/Network/Validators/EmailTest.php +++ b/tests/unit/Network/Validators/EmailTest.php @@ -3,12 +3,13 @@ /** * Utopia PHP Framework * - * @package Framework - * @subpackage Tests * * @link https://github.com/utopia-php/framework + * * @author Appwrite Team + * * @version 1.0 RC4 + * * @license The MIT License (MIT) */ diff --git a/tests/unit/Template/TemplateTest.php b/tests/unit/Template/TemplateTest.php index 1ca1595ca3..ab4cb49742 100644 --- a/tests/unit/Template/TemplateTest.php +++ b/tests/unit/Template/TemplateTest.php @@ -14,10 +14,9 @@ class TemplateTest extends TestCase public function setUp(): void { - $this->object = new Template(__DIR__ . '/../../resources/template.tpl'); + $this->object = new Template(__DIR__.'/../../resources/template.tpl'); $this->object - ->setParam('{{world}}', 'WORLD') - ; + ->setParam('{{world}}', 'WORLD'); } public function tearDown(): void diff --git a/tests/unit/Usage/StatsTest.php b/tests/unit/Usage/StatsTest.php index 0c9914f4bd..72fadab70e 100644 --- a/tests/unit/Usage/StatsTest.php +++ b/tests/unit/Usage/StatsTest.php @@ -13,25 +13,26 @@ use Utopia\Queue\Connection; class StatsTest extends TestCase { protected ?Connection $connection = null; + protected ?Client $client = null; protected const QUEUE_NAME = 'usage-test-q'; public function setUp(): void { - $env = App::getEnv('_APP_CONNECTIONS_QUEUE', AppwriteURL::unparse([ - 'scheme' => 'redis', - 'host' => App::getEnv('_APP_REDIS_HOST', 'redis'), - 'port' => App::getEnv('_APP_REDIS_PORT', '6379'), - 'user' => App::getEnv('_APP_REDIS_USER', ''), - 'pass' => App::getEnv('_APP_REDIS_PASS', ''), - ])); + $env = App::getEnv('_APP_CONNECTIONS_QUEUE', AppwriteURL::unparse([ + 'scheme' => 'redis', + 'host' => App::getEnv('_APP_REDIS_HOST', 'redis'), + 'port' => App::getEnv('_APP_REDIS_PORT', '6379'), + 'user' => App::getEnv('_APP_REDIS_USER', ''), + 'pass' => App::getEnv('_APP_REDIS_PASS', ''), + ])); $dsn = explode('=', $env); $dsn = $dsn[1] ?? ''; $dsn = new DSN($dsn); $this->connection = new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort()); - $this->client = new Client(self::QUEUE_NAME, $this->connection); + $this->client = new Client(self::QUEUE_NAME, $this->connection); } public function tearDown(): void @@ -41,13 +42,13 @@ class StatsTest extends TestCase public function testSamePayload(): void { $inToQueue = [ - 'key_1' => 'value_1', - 'key_2' => 'value_2', + 'key_1' => 'value_1', + 'key_2' => 'value_2', ]; $result = $this->client->enqueue($inToQueue); $this->assertTrue($result); - $outFromQueue = $this->connection->leftPopArray('utopia-queue.queue.' . self::QUEUE_NAME, 0)['payload']; + $outFromQueue = $this->connection->leftPopArray('utopia-queue.queue.'.self::QUEUE_NAME, 0)['payload']; $this->assertNotEmpty($outFromQueue); $this->assertSame($inToQueue, $outFromQueue); } diff --git a/tests/unit/Utopia/Lists.php b/tests/unit/Utopia/Lists.php index 8f003cc2ae..ac54a293a5 100644 --- a/tests/unit/Utopia/Lists.php +++ b/tests/unit/Utopia/Lists.php @@ -12,7 +12,7 @@ class Lists extends Model ->addRule('singles', [ 'type' => 'single', 'default' => '', - 'array' => true + 'array' => true, ]); } diff --git a/tests/unit/Utopia/Nested.php b/tests/unit/Utopia/Nested.php index 2be0e85762..b18f73977e 100644 --- a/tests/unit/Utopia/Nested.php +++ b/tests/unit/Utopia/Nested.php @@ -15,7 +15,7 @@ class Nested extends Model ]) ->addRule('single', [ 'type' => 'single', - 'default' => '' + 'default' => '', ]); } diff --git a/tests/unit/Utopia/Request/Filters/V15Test.php b/tests/unit/Utopia/Request/Filters/V15Test.php index 70bf71d4cb..7a37213d44 100644 --- a/tests/unit/Utopia/Request/Filters/V15Test.php +++ b/tests/unit/Utopia/Request/Filters/V15Test.php @@ -28,7 +28,7 @@ class V15Test extends TestCase return [ 'basic test' => [ ['limit' => '12', 'offset' => '0'], - ['queries' => ['limit(12)', 'offset(0)']] + ['queries' => ['limit(12)', 'offset(0)']], ], ]; } @@ -72,8 +72,8 @@ class V15Test extends TestCase 'limit(12)', 'offset(0)', 'cursorBefore("abcd")', - 'orderAsc("")' - ] + 'orderAsc("")', + ], ], ], ]; @@ -90,7 +90,7 @@ class V15Test extends TestCase [ 'queries' => [ 'cursorAfter("abcd")', - ] + ], ], ], 'cursorDirection invalid' => [ @@ -101,7 +101,7 @@ class V15Test extends TestCase [ 'queries' => [ 'cursorAfter("abcd")', - ] + ], ], ], ]; @@ -117,7 +117,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderDesc("")', - ] + ], ], ], 'orderType invalid' => [ @@ -127,7 +127,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderAsc("")', - ] + ], ], ], ]; @@ -239,7 +239,7 @@ class V15Test extends TestCase 'write invalid' => [ ['write' => ['invalid', 'invalid:a']], ['permissions' => ['write("invalid:a")']], - ] + ], ]; } @@ -320,7 +320,7 @@ class V15Test extends TestCase 'queries' => [ 'orderDesc("lastName")', 'orderAsc("firstName")', - ] + ], ], ], 'orderType only' => [ @@ -330,7 +330,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderDesc("")', - ] + ], ], ], 'orderType invalid' => [ @@ -341,7 +341,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderAsc("lastName")', - ] + ], ], ], ]; @@ -371,7 +371,7 @@ class V15Test extends TestCase 'greaterThan("age", [20])', 'greaterThanEqual("age", [21])', 'search("address", ["pla"])', - ] + ], ], ], ]; @@ -439,7 +439,7 @@ class V15Test extends TestCase 'team:b', 'team:c/member', 'member:z', - ] + ], ], ], ]; diff --git a/tests/unit/Utopia/Response/Filters/V15Test.php b/tests/unit/Utopia/Response/Filters/V15Test.php index fc38e5320b..cf08d9bb70 100644 --- a/tests/unit/Utopia/Response/Filters/V15Test.php +++ b/tests/unit/Utopia/Response/Filters/V15Test.php @@ -2,11 +2,11 @@ namespace Tests\Unit\Utopia\Response\Filters; -use Appwrite\Utopia\Response\Filters\V15; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Filters\V15; +use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use PHPUnit\Framework\TestCase; class V15Test extends TestCase { @@ -196,7 +196,7 @@ class V15Test extends TestCase 'maximumFileSize' => 100, 'allowedFileExtensions' => [ 'jpg', - 'png' + 'png', ], 'encryption' => false, 'antivirus' => false, @@ -213,7 +213,7 @@ class V15Test extends TestCase 'maximumFileSize' => 100, 'allowedFileExtensions' => [ 'jpg', - 'png' + 'png', ], 'encryption' => false, 'antivirus' => false, @@ -275,8 +275,8 @@ class V15Test extends TestCase [ 'startTime' => 1592981250, 'endTime' => 1592981250, - ] - ] + ], + ], ]; } @@ -346,14 +346,14 @@ class V15Test extends TestCase 'status' => 'available', 'required' => true, 'array' => false, - 'default' => false + 'default' => false, ], 'indexes' => [ 'key' => 'index1', 'type' => 'primary', 'status' => 'available', 'attributes' => [], - 'orders' => [] + 'orders' => [], ], ], [ @@ -361,10 +361,10 @@ class V15Test extends TestCase '$createdAt' => 1592981250, '$updatedAt' => 1592981250, '$read' => [ - 'role:all' + 'role:all', ], '$write' => [ - 'user:608f9da25e7e1' + 'user:608f9da25e7e1', ], 'databaseId' => '5e5ea5c16897e', 'name' => 'My Collection', @@ -376,14 +376,14 @@ class V15Test extends TestCase 'status' => 'available', 'required' => true, 'array' => false, - 'default' => false + 'default' => false, ], 'indexes' => [ 'key' => 'index1', 'type' => 'primary', 'status' => 'available', 'attributes' => [], - 'orders' => [] + 'orders' => [], ], ], ], @@ -511,7 +511,7 @@ class V15Test extends TestCase '$databaseId' => '5e5ea5c15117e', '$createdAt' => '2020-06-24T06:47:30.000Z', '$updatedAt' => '2020-06-24T06:47:30.000Z', - '$permissions' => [Permission::read(Role::any())] + '$permissions' => [Permission::read(Role::any())], ], [ '$id' => '5e5ea5c16897e', @@ -605,7 +605,7 @@ class V15Test extends TestCase '$createdAt' => '2020-06-24T06:47:30.000Z', '$updatedAt' => '2020-06-24T06:47:30.000Z', '$permissions' => [ - "any" + 'any', ], 'functionId' => '5e5ea6g16897e', 'trigger' => 'http', @@ -614,14 +614,14 @@ class V15Test extends TestCase 'response' => '', 'stdout' => '', 'stderr' => '', - 'duration' => 0.4 + 'duration' => 0.4, ], [ '$id' => '5e5ea5c16897e', '$createdAt' => 1592981250, '$updatedAt' => 1592981250, '$read' => [ - "role:all" + 'role:all', ], 'functionId' => '5e5ea6g16897e', 'trigger' => 'http', @@ -629,7 +629,7 @@ class V15Test extends TestCase 'statusCode' => 0, 'response' => '', 'stderr' => '', - 'time' => 0.4 + 'time' => 0.4, ], ], ]; @@ -730,37 +730,37 @@ class V15Test extends TestCase 'key' => 'key', 'value' => 'value', 'functionId' => '5e5ea5c16897e', - ] + ], ], 'events' => [ - 'account.create' + 'account.create', ], 'schedule' => '5 4 * * *', 'scheduleNext' => '2020-06-24T06:48:12.000Z', 'schedulePrevious' => '2020-06-24T06:47:17.000Z', - 'timeout' => 1592981237 + 'timeout' => 1592981237, ], [ '$id' => '5e5ea5c16897e', '$createdAt' => 1592981250, '$updatedAt' => 1592981250, 'execute' => [ - 'role:member' + 'role:member', ], 'name' => 'My Function', 'status' => 'enabled', 'runtime' => 'python-3.8', 'deployment' => '5e5ea5c16897e', 'vars' => [ - 'key' => 'value' + 'key' => 'value', ], 'events' => [ - 'account.create' + 'account.create', ], 'schedule' => '5 4 * * *', 'scheduleNext' => 1592981292, 'schedulePrevious' => 1592981237, - 'timeout' => 1592981237 + 'timeout' => 1592981237, ], ], 'enabled false' => [ @@ -877,7 +877,7 @@ class V15Test extends TestCase 'deviceBrand' => 'Google', 'deviceModel' => 'Nexus 5', 'countryCode' => 'US', - 'countryName' => 'United States' + 'countryName' => 'United States', ], [ 'event' => 'account.sessions.create', @@ -900,8 +900,8 @@ class V15Test extends TestCase 'deviceBrand' => 'Google', 'deviceModel' => 'Nexus 5', 'countryCode' => 'US', - 'countryName' => 'United States' - ] + 'countryName' => 'United States', + ], ], ]; } diff --git a/tests/unit/Utopia/ResponseTest.php b/tests/unit/Utopia/ResponseTest.php index e4389b3953..f7be5a03a4 100644 --- a/tests/unit/Utopia/ResponseTest.php +++ b/tests/unit/Utopia/ResponseTest.php @@ -2,9 +2,9 @@ namespace Tests\Unit\Utopia; -use Exception; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filters\V11; +use Exception; use PHPUnit\Framework\TestCase; use Swoole\Http\Response as SwooleResponse; use Utopia\Database\Document; @@ -80,8 +80,8 @@ class ResponseTest extends TestCase 'string' => 'lorem ipsum', 'integer' => 123, 'boolean' => true, - 'hidden' => 'secret' - ]) + 'hidden' => 'secret', + ]), ], 'hidden' => 'secret', ]), 'lists'); @@ -107,8 +107,8 @@ class ResponseTest extends TestCase 'string' => 'lorem ipsum', 'integer' => 123, 'boolean' => true, - 'hidden' => 'secret' - ]) + 'hidden' => 'secret', + ]), ], 'hidden' => 'secret', ]), @@ -116,7 +116,7 @@ class ResponseTest extends TestCase 'string' => 'lorem ipsum', 'integer' => 123, 'boolean' => true, - 'hidden' => 'secret' + 'hidden' => 'secret', ]), 'hidden' => 'secret', ]), 'nested'); @@ -126,7 +126,6 @@ class ResponseTest extends TestCase $this->assertArrayNotHasKey('hidden', $output); $this->assertCount(1, $output['lists']['singles']); - $single = $output['single']; $this->assertArrayHasKey('string', $single); $this->assertArrayHasKey('integer', $single); diff --git a/tests/unit/Utopia/Single.php b/tests/unit/Utopia/Single.php index 3bd09ef6da..6e9fd3c9ec 100644 --- a/tests/unit/Utopia/Single.php +++ b/tests/unit/Utopia/Single.php @@ -12,7 +12,7 @@ class Single extends Model ->addRule('string', [ 'type' => self::TYPE_STRING, 'example' => '5e5ea5c16897e', - 'required' => true + 'required' => true, ]) ->addRule('integer', [ 'type' => self::TYPE_INTEGER, @@ -27,7 +27,7 @@ class Single extends Model ->addRule('required', [ 'type' => self::TYPE_STRING, 'default' => 'default', - 'required' => true + 'required' => true, ]); } From ac33d7828f0079169a461b7e931ad8830ce1772c Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 01:53:52 +0530 Subject: [PATCH 19/72] Revert "Pint linter ran" This reverts commit bf5f0a841921920e3a2cca09875fa9946d73ce89. --- app/cli.php | 31 +- app/config/authProviders.php | 14 +- app/config/avatars/browsers.php | 29 +- app/config/avatars/credit-cards.php | 34 +- app/config/avatars/flags.php | 388 +++--- app/config/avatars/os.php | 6 +- app/config/collections.php | 48 +- app/config/errors.php | 8 +- app/config/events.php | 66 +- app/config/locale/codes.php | 525 ++++---- app/config/locale/languages.php | 1106 ++++++++--------- app/config/locale/templates.php | 4 +- app/config/messagingProviders.php | 586 ++++----- app/config/platforms.php | 44 +- app/config/regions.php | 2 +- app/config/roles.php | 4 +- app/config/runtimes.php | 2 +- app/config/scopes.php | 4 +- app/config/services.php | 6 +- app/config/usage.php | 40 +- app/config/variables.php | 196 +-- app/controllers/api/account.php | 527 ++++---- app/controllers/api/avatars.php | 169 +-- app/controllers/api/console.php | 3 + app/controllers/api/databases.php | 642 +++++----- app/controllers/api/functions.php | 205 +-- app/controllers/api/graphql.php | 23 +- app/controllers/api/health.php | 98 +- app/controllers/api/locale.php | 27 +- app/controllers/api/messaging.php | 788 ++++++------ app/controllers/api/migrations.php | 40 +- app/controllers/api/project.php | 28 +- app/controllers/api/projects.php | 178 ++- app/controllers/api/storage.php | 306 ++--- app/controllers/api/teams.php | 175 +-- app/controllers/api/users.php | 141 ++- app/controllers/general.php | 157 +-- app/controllers/mock.php | 67 +- app/controllers/shared/api.php | 107 +- app/controllers/shared/api/auth.php | 3 +- app/controllers/web/console.php | 24 +- app/controllers/web/home.php | 4 +- app/http.php | 76 +- app/init.php | 303 +++-- app/preload.php | 40 +- app/realtime.php | 147 +-- app/worker.php | 40 +- app/workers/audits.php | 6 +- app/workers/builds.php | 39 +- app/workers/certificates.php | 144 ++- app/workers/databases.php | 104 +- app/workers/deletes.php | 275 ++-- app/workers/functions.php | 40 +- app/workers/mails.php | 18 +- app/workers/messaging.php | 35 +- app/workers/migrations.php | 4 +- app/workers/usage.php | 92 +- app/workers/webhooks.php | 30 +- src/Appwrite/Auth/Auth.php | 117 +- src/Appwrite/Auth/Hash.php | 25 +- src/Appwrite/Auth/Hash/Argon2.php | 10 +- src/Appwrite/Auth/Hash/Bcrypt.php | 12 +- src/Appwrite/Auth/Hash/Md5.php | 10 +- src/Appwrite/Auth/Hash/Phpass.php | 61 +- src/Appwrite/Auth/Hash/Scrypt.php | 12 +- src/Appwrite/Auth/Hash/Scryptmodified.php | 14 +- src/Appwrite/Auth/Hash/Sha.php | 12 +- src/Appwrite/Auth/OAuth2.php | 56 +- src/Appwrite/Auth/OAuth2/Amazon.php | 40 +- src/Appwrite/Auth/OAuth2/Apple.php | 47 +- src/Appwrite/Auth/OAuth2/Auth0.php | 41 +- src/Appwrite/Auth/OAuth2/Authentik.php | 47 +- src/Appwrite/Auth/OAuth2/Autodesk.php | 29 +- src/Appwrite/Auth/OAuth2/Bitbucket.php | 32 +- src/Appwrite/Auth/OAuth2/Bitly.php | 57 +- src/Appwrite/Auth/OAuth2/Box.php | 53 +- src/Appwrite/Auth/OAuth2/Dailymotion.php | 50 +- src/Appwrite/Auth/OAuth2/Discord.php | 39 +- src/Appwrite/Auth/OAuth2/Disqus.php | 36 +- src/Appwrite/Auth/OAuth2/Dropbox.php | 31 +- src/Appwrite/Auth/OAuth2/Etsy.php | 33 +- src/Appwrite/Auth/OAuth2/Exception.php | 6 +- src/Appwrite/Auth/OAuth2/Facebook.php | 39 +- src/Appwrite/Auth/OAuth2/Firebase.php | 75 +- src/Appwrite/Auth/OAuth2/Github.php | 40 +- src/Appwrite/Auth/OAuth2/Gitlab.php | 40 +- src/Appwrite/Auth/OAuth2/Google.php | 37 +- src/Appwrite/Auth/OAuth2/Linkedin.php | 33 +- src/Appwrite/Auth/OAuth2/Microsoft.php | 40 +- src/Appwrite/Auth/OAuth2/Mock.php | 38 +- src/Appwrite/Auth/OAuth2/Notion.php | 43 +- src/Appwrite/Auth/OAuth2/Oidc.php | 82 +- src/Appwrite/Auth/OAuth2/Okta.php | 41 +- src/Appwrite/Auth/OAuth2/Paypal.php | 41 +- src/Appwrite/Auth/OAuth2/PaypalSandbox.php | 2 + src/Appwrite/Auth/OAuth2/Podio.php | 41 +- src/Appwrite/Auth/OAuth2/Salesforce.php | 42 +- src/Appwrite/Auth/OAuth2/Slack.php | 39 +- src/Appwrite/Auth/OAuth2/Spotify.php | 47 +- src/Appwrite/Auth/OAuth2/Stripe.php | 37 +- src/Appwrite/Auth/OAuth2/Tradeshift.php | 52 +- src/Appwrite/Auth/OAuth2/TradeshiftBox.php | 2 + src/Appwrite/Auth/OAuth2/Twitch.php | 53 +- src/Appwrite/Auth/OAuth2/WordPress.php | 31 +- src/Appwrite/Auth/OAuth2/Yahoo.php | 49 +- src/Appwrite/Auth/OAuth2/Yammer.php | 37 +- src/Appwrite/Auth/OAuth2/Yandex.php | 43 +- src/Appwrite/Auth/OAuth2/Zoom.php | 39 +- src/Appwrite/Auth/Validator/Password.php | 5 +- .../Auth/Validator/PasswordDictionary.php | 7 +- .../Auth/Validator/PasswordHistory.php | 6 +- src/Appwrite/Auth/Validator/PersonalData.php | 7 +- src/Appwrite/Auth/Validator/Phone.php | 5 +- src/Appwrite/Detector/Detector.php | 8 +- src/Appwrite/Docker/Compose.php | 4 +- src/Appwrite/Docker/Compose/Service.php | 5 +- src/Appwrite/Docker/Env.php | 14 +- src/Appwrite/Event/Audit.php | 12 +- src/Appwrite/Event/Build.php | 11 +- src/Appwrite/Event/Certificate.php | 8 +- src/Appwrite/Event/Database.php | 17 +- src/Appwrite/Event/Delete.php | 19 +- src/Appwrite/Event/Event.php | 78 +- src/Appwrite/Event/Func.php | 20 +- src/Appwrite/Event/Mail.php | 37 +- src/Appwrite/Event/Migration.php | 14 +- src/Appwrite/Event/Phone.php | 8 +- src/Appwrite/Event/Usage.php | 13 +- src/Appwrite/Event/Validator/Event.php | 24 +- src/Appwrite/Extend/Exception.php | 371 ++---- src/Appwrite/GraphQL/Promises/Adapter.php | 21 +- src/Appwrite/GraphQL/Resolvers.php | 129 +- src/Appwrite/GraphQL/Schema.php | 68 +- src/Appwrite/GraphQL/Types.php | 3 - src/Appwrite/GraphQL/Types/Assoc.php | 8 +- src/Appwrite/GraphQL/Types/InputFile.php | 3 +- src/Appwrite/GraphQL/Types/Json.php | 4 +- src/Appwrite/GraphQL/Types/Mapper.php | 49 +- src/Appwrite/GraphQL/Types/Registry.php | 8 +- src/Appwrite/Messaging/Adapter.php | 2 - src/Appwrite/Messaging/Adapter/Realtime.php | 84 +- src/Appwrite/Migration/Migration.php | 80 +- src/Appwrite/Migration/Version/V15.php | 47 +- src/Appwrite/Migration/Version/V16.php | 14 +- src/Appwrite/Migration/Version/V17.php | 12 +- src/Appwrite/Migration/Version/V18.php | 6 +- src/Appwrite/Migration/Version/V19.php | 11 +- src/Appwrite/Network/Validator/CNAME.php | 9 +- src/Appwrite/Network/Validator/Email.php | 6 +- src/Appwrite/Network/Validator/Origin.php | 39 +- src/Appwrite/OpenSSL/OpenSSL.php | 26 +- src/Appwrite/Platform/Services/Tasks.php | 20 +- src/Appwrite/Platform/Tasks/CalcTierStats.php | 54 +- .../Platform/Tasks/CalcUsersStats.php | 27 +- .../Platform/Tasks/ClearCardCache.php | 14 +- src/Appwrite/Platform/Tasks/Doctor.php | 93 +- src/Appwrite/Platform/Tasks/Hamster.php | 95 +- src/Appwrite/Platform/Tasks/Install.php | 68 +- src/Appwrite/Platform/Tasks/Maintenance.php | 18 +- src/Appwrite/Platform/Tasks/Migrate.php | 21 +- .../Tasks/PatchCreateMissingSchedules.php | 16 +- .../Tasks/PatchDeleteProjectCollections.php | 22 +- .../PatchDeleteScheduleUpdatedAtAttribute.php | 12 +- src/Appwrite/Platform/Tasks/SDKs.php | 86 +- src/Appwrite/Platform/Tasks/SSL.php | 6 +- src/Appwrite/Platform/Tasks/Schedule.php | 37 +- src/Appwrite/Platform/Tasks/Specs.php | 50 +- src/Appwrite/Platform/Tasks/Vars.php | 4 +- src/Appwrite/Platform/Tasks/VolumeSync.php | 16 +- src/Appwrite/Promises/Promise.php | 35 +- src/Appwrite/Promises/Swoole.php | 4 +- src/Appwrite/Resque/Worker.php | 84 +- src/Appwrite/Specification/Format.php | 31 +- .../Specification/Format/OpenAPI3.php | 92 +- .../Specification/Format/Swagger2.php | 82 +- src/Appwrite/Task/Validator/Cron.php | 5 +- src/Appwrite/Template/Template.php | 37 +- src/Appwrite/URL/URL.php | 34 +- .../Utopia/Database/Validator/CustomId.php | 2 + .../Utopia/Database/Validator/ProjectId.php | 1 + .../Database/Validator/Queries/Attributes.php | 5 +- .../Database/Validator/Queries/Base.php | 20 +- .../Database/Validator/Queries/Buckets.php | 3 +- .../Validator/Queries/Collections.php | 3 +- .../Database/Validator/Queries/Databases.php | 3 +- .../Validator/Queries/Deployments.php | 1 + .../Database/Validator/Queries/Executions.php | 3 +- .../Database/Validator/Queries/Files.php | 3 +- .../Database/Validator/Queries/Functions.php | 3 +- .../Database/Validator/Queries/Identities.php | 1 + .../Database/Validator/Queries/Indexes.php | 1 + .../Validator/Queries/Memberships.php | 3 +- .../Database/Validator/Queries/Migrations.php | 3 +- .../Database/Validator/Queries/Projects.php | 5 +- .../Database/Validator/Queries/Providers.php | 1 + .../Database/Validator/Queries/Teams.php | 3 +- .../Database/Validator/Queries/Users.php | 3 +- .../Database/Validator/Queries/Variables.php | 5 +- src/Appwrite/Utopia/Request.php | 11 +- src/Appwrite/Utopia/Request/Filter.php | 5 +- src/Appwrite/Utopia/Request/Filters/V12.php | 45 +- src/Appwrite/Utopia/Request/Filters/V13.php | 16 +- src/Appwrite/Utopia/Request/Filters/V14.php | 12 +- src/Appwrite/Utopia/Request/Filters/V15.php | 25 +- src/Appwrite/Utopia/Response.php | 246 +--- src/Appwrite/Utopia/Response/Filter.php | 5 +- src/Appwrite/Utopia/Response/Filters/V11.php | 35 +- src/Appwrite/Utopia/Response/Filters/V12.php | 12 - src/Appwrite/Utopia/Response/Filters/V13.php | 3 - src/Appwrite/Utopia/Response/Filters/V15.php | 18 +- src/Appwrite/Utopia/Response/Model.php | 16 +- .../Utopia/Response/Model/AlgoArgon2.php | 3 +- .../Utopia/Response/Model/AlgoScrypt.php | 3 +- .../Response/Model/AlgoScryptModified.php | 3 +- .../Utopia/Response/Model/Attribute.php | 3 +- .../Response/Model/AttributeBoolean.php | 7 +- .../Response/Model/AttributeDatetime.php | 5 +- .../Utopia/Response/Model/AttributeEmail.php | 5 +- .../Utopia/Response/Model/AttributeEnum.php | 5 +- .../Utopia/Response/Model/AttributeFloat.php | 3 +- .../Utopia/Response/Model/AttributeIP.php | 5 +- .../Response/Model/AttributeInteger.php | 4 +- .../Utopia/Response/Model/AttributeList.php | 7 +- .../Response/Model/AttributeRelationship.php | 6 +- .../Utopia/Response/Model/AttributeString.php | 3 +- .../Utopia/Response/Model/AttributeURL.php | 5 +- .../Utopia/Response/Model/AuthProvider.php | 3 +- .../Utopia/Response/Model/BaseList.php | 20 +- src/Appwrite/Utopia/Response/Model/Bucket.php | 9 +- src/Appwrite/Utopia/Response/Model/Build.php | 3 +- .../Utopia/Response/Model/Collection.php | 7 +- .../Utopia/Response/Model/Continent.php | 3 +- .../Utopia/Response/Model/Country.php | 3 +- .../Utopia/Response/Model/Currency.php | 3 +- .../Utopia/Response/Model/Database.php | 3 +- .../Utopia/Response/Model/Deployment.php | 3 +- src/Appwrite/Utopia/Response/Model/Domain.php | 3 +- src/Appwrite/Utopia/Response/Model/Error.php | 3 +- .../Utopia/Response/Model/ErrorDev.php | 3 +- .../Utopia/Response/Model/Execution.php | 3 +- src/Appwrite/Utopia/Response/Model/File.php | 3 +- src/Appwrite/Utopia/Response/Model/Func.php | 7 +- .../Utopia/Response/Model/HealthAntivirus.php | 3 +- .../Utopia/Response/Model/HealthQueue.php | 3 +- .../Utopia/Response/Model/HealthStatus.php | 3 +- .../Utopia/Response/Model/HealthTime.php | 3 +- .../Utopia/Response/Model/HealthVersion.php | 3 +- .../Utopia/Response/Model/Identity.php | 3 +- src/Appwrite/Utopia/Response/Model/Index.php | 3 +- src/Appwrite/Utopia/Response/Model/JWT.php | 3 +- src/Appwrite/Utopia/Response/Model/Key.php | 9 +- .../Utopia/Response/Model/Language.php | 3 +- src/Appwrite/Utopia/Response/Model/Locale.php | 3 +- .../Utopia/Response/Model/LocaleCode.php | 3 +- src/Appwrite/Utopia/Response/Model/Log.php | 3 +- .../Utopia/Response/Model/Membership.php | 3 +- src/Appwrite/Utopia/Response/Model/Metric.php | 2 +- .../Utopia/Response/Model/Migration.php | 5 +- src/Appwrite/Utopia/Response/Model/Mock.php | 3 +- src/Appwrite/Utopia/Response/Model/Phone.php | 3 +- .../Utopia/Response/Model/Platform.php | 3 +- .../Utopia/Response/Model/Project.php | 37 +- .../Utopia/Response/Model/Runtime.php | 5 +- .../Utopia/Response/Model/Session.php | 3 +- src/Appwrite/Utopia/Response/Model/Team.php | 4 +- .../Utopia/Response/Model/Template.php | 3 +- .../Utopia/Response/Model/TemplateEmail.php | 3 +- .../Utopia/Response/Model/TemplateSMS.php | 1 - src/Appwrite/Utopia/Response/Model/Token.php | 3 +- .../Utopia/Response/Model/UsageBuckets.php | 7 +- .../Utopia/Response/Model/UsageCollection.php | 5 +- .../Utopia/Response/Model/UsageDatabase.php | 7 +- .../Utopia/Response/Model/UsageDatabases.php | 9 +- .../Utopia/Response/Model/UsageFunction.php | 17 +- .../Utopia/Response/Model/UsageFunctions.php | 19 +- .../Utopia/Response/Model/UsageProject.php | 19 +- .../Utopia/Response/Model/UsageStorage.php | 9 +- .../Utopia/Response/Model/UsageUsers.php | 7 +- src/Appwrite/Utopia/Response/Model/User.php | 6 +- .../Utopia/Response/Model/Variable.php | 3 +- .../Utopia/Response/Model/Webhook.php | 3 +- src/Appwrite/Utopia/View.php | 3 +- src/Executor/Executor.php | 104 +- tests/e2e/Client.php | 66 +- tests/e2e/General/AbuseTest.php | 42 +- tests/e2e/General/HTTPTest.php | 8 +- tests/e2e/General/UsageTest.php | 111 +- tests/e2e/Scopes/ProjectCustom.php | 23 +- tests/e2e/Scopes/Scope.php | 11 +- tests/e2e/Scopes/SideClient.php | 2 +- tests/e2e/Scopes/SideConsole.php | 4 +- tests/e2e/Scopes/SideServer.php | 2 +- tests/e2e/Services/Account/AccountBase.php | 197 +-- .../Account/AccountConsoleClientTest.php | 14 +- .../Account/AccountCustomClientTest.php | 141 ++- .../Account/AccountCustomServerTest.php | 2 +- tests/e2e/Services/Avatars/AvatarsBase.php | 17 +- .../Avatars/AvatarsConsoleClientTest.php | 2 +- .../Avatars/AvatarsCustomClientTest.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 900 +++++++------- .../Databases/DatabasesConsoleClientTest.php | 84 +- .../Databases/DatabasesCustomClientTest.php | 269 ++-- .../Databases/DatabasesCustomServerTest.php | 1088 ++++++++-------- .../DatabasesPermissionsGuestTest.php | 48 +- .../DatabasesPermissionsMemberTest.php | 40 +- .../Databases/DatabasesPermissionsScope.php | 15 +- .../DatabasesPermissionsTeamTest.php | 27 +- .../e2e/Services/Functions/FunctionsBase.php | 3 +- .../Functions/FunctionsConsoleClientTest.php | 125 +- .../Functions/FunctionsCustomClientTest.php | 105 +- .../Functions/FunctionsCustomServerTest.php | 231 ++-- tests/e2e/Services/GraphQL/AbuseTest.php | 8 +- tests/e2e/Services/GraphQL/AccountTest.php | 36 +- tests/e2e/Services/GraphQL/AuthTest.php | 49 +- tests/e2e/Services/GraphQL/Base.php | 155 +-- tests/e2e/Services/GraphQL/BatchTest.php | 39 +- .../e2e/Services/GraphQL/ContentTypeTest.php | 8 +- .../Services/GraphQL/DatabaseClientTest.php | 22 +- .../Services/GraphQL/DatabaseServerTest.php | 137 +- .../Services/GraphQL/FunctionsClientTest.php | 26 +- .../Services/GraphQL/FunctionsServerTest.php | 54 +- .../e2e/Services/GraphQL/LocalizationTest.php | 2 +- tests/e2e/Services/GraphQL/ScopeTest.php | 5 +- .../Services/GraphQL/StorageClientTest.php | 36 +- .../Services/GraphQL/StorageServerTest.php | 49 +- .../e2e/Services/GraphQL/TeamsServerTest.php | 8 +- tests/e2e/Services/GraphQL/UsersTest.php | 39 +- tests/e2e/Services/Health/HealthBase.php | 2 + .../Health/HealthCustomServerTest.php | 3 +- tests/e2e/Services/Locale/LocaleBase.php | 16 +- .../Locale/LocaleConsoleClientTest.php | 2 +- .../Locale/LocaleCustomClientTest.php | 2 +- .../Locale/LocaleCustomServerTest.php | 1 + .../Messaging/MessagingServerTest.php | 9 +- tests/e2e/Services/Projects/ProjectsBase.php | 2 + .../Projects/ProjectsConsoleClientTest.php | 485 ++++---- .../Projects/ProjectsCustomClientTest.php | 3 +- .../Projects/ProjectsCustomServerTest.php | 1 + tests/e2e/Services/Realtime/RealtimeBase.php | 12 +- .../Realtime/RealtimeConsoleClientTest.php | 53 +- .../Realtime/RealtimeCustomClientTest.php | 331 ++--- tests/e2e/Services/Storage/StorageBase.php | 161 +-- .../Storage/StorageConsoleClientTest.php | 29 +- .../Storage/StorageCustomClientTest.php | 419 +++---- .../Storage/StorageCustomServerTest.php | 46 +- .../Storage/StoragePermissionsScope.php | 16 +- tests/e2e/Services/Teams/TeamsBase.php | 47 +- tests/e2e/Services/Teams/TeamsBaseClient.php | 155 +-- tests/e2e/Services/Teams/TeamsBaseServer.php | 52 +- .../Services/Teams/TeamsConsoleClientTest.php | 34 +- .../Services/Teams/TeamsCustomClientTest.php | 2 +- .../Services/Teams/TeamsCustomServerTest.php | 1 + tests/e2e/Services/Users/UsersBase.php | 134 +- .../Services/Users/UsersConsoleClientTest.php | 9 +- .../Services/Users/UsersCustomServerTest.php | 1 + tests/e2e/Services/Webhooks/WebhooksBase.php | 136 +- .../Webhooks/WebhooksCustomClientTest.php | 102 +- .../Webhooks/WebhooksCustomServerTest.php | 77 +- tests/extensions/Retryable.php | 13 +- tests/extensions/TestHook.php | 2 +- tests/resources/functions/php-fn/index.php | 2 +- tests/resources/functions/php-large/index.php | 2 +- tests/resources/functions/php/index.php | 2 +- tests/unit/Auth/AuthTest.php | 62 +- .../Auth/Validator/PasswordDictionaryTest.php | 1 + tests/unit/Docker/ComposeTest.php | 2 +- tests/unit/Docker/EnvTest.php | 6 +- tests/unit/Event/EventTest.php | 12 +- tests/unit/General/CollectionsTest.php | 2 +- .../unit/Messaging/MessagingChannelsTest.php | 53 +- tests/unit/Messaging/MessagingGuestTest.php | 4 +- tests/unit/Messaging/MessagingTest.php | 28 +- tests/unit/Migration/MigrationTest.php | 50 +- tests/unit/Network/Validators/EmailTest.php | 5 +- tests/unit/Template/TemplateTest.php | 5 +- tests/unit/Usage/StatsTest.php | 23 +- tests/unit/Utopia/Lists.php | 2 +- tests/unit/Utopia/Nested.php | 2 +- tests/unit/Utopia/Request/Filters/V15Test.php | 26 +- .../unit/Utopia/Response/Filters/V15Test.php | 54 +- tests/unit/Utopia/ResponseTest.php | 13 +- tests/unit/Utopia/Single.php | 4 +- 382 files changed, 10328 insertions(+), 10216 deletions(-) diff --git a/app/cli.php b/app/cli.php index 2614e00e11..d1dd885775 100644 --- a/app/cli.php +++ b/app/cli.php @@ -1,27 +1,27 @@ $register); +CLI::setResource('register', fn()=>$register); CLI::setResource('cache', function ($pools) { $list = Config::getParam('pools-cache', []); @@ -31,7 +31,8 @@ CLI::setResource('cache', function ($pools) { $adapters[] = $pools ->get($value) ->pop() - ->getResource(); + ->getResource() + ; } return new Cache(new Sharding($adapters)); @@ -63,7 +64,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { $collections = Config::getParam('collections', [])['console']; $last = \array_key_last($collections); - if (! ($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */ + if (!($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */ throw new Exception('Tables not ready yet.'); } @@ -75,8 +76,8 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { } } while ($attempts < $maxAttempts); - if (! $ready) { - throw new Exception('Console is not ready yet. Please try again later.'); + if (!$ready) { + throw new Exception("Console is not ready yet. Please try again later."); } return $dbForConsole; @@ -94,8 +95,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - $database->setNamespace('_'.$project->getInternalId()); - + $database->setNamespace('_' . $project->getInternalId()); return $database; } @@ -108,7 +108,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; - $database->setNamespace('_'.$project->getInternalId()); + $database->setNamespace('_' . $project->getInternalId()); return $database; }; @@ -116,6 +116,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $getProjectDB; }, ['pools', 'dbForConsole', 'cache']); + CLI::setResource('queueForFunctions', function (Group $pools) { return new Func($pools->get('queue')->pop()->getResource()); }, ['pools']); @@ -148,7 +149,7 @@ CLI::setResource('logError', function (Registry $register) { $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('Usage stats log pushed with status code: '.$responseCode); + Console::info('Usage stats log pushed with status code: ' . $responseCode); } Console::warning("Failed: {$error->getMessage()}"); diff --git a/app/config/authProviders.php b/app/config/authProviders.php index cf9ad052c3..dedb4ec665 100644 --- a/app/config/authProviders.php +++ b/app/config/authProviders.php @@ -69,7 +69,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'box' => [ 'name' => 'Box', @@ -79,7 +79,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'dailymotion' => [ 'name' => 'Dailymotion', @@ -89,7 +89,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'discord' => [ 'name' => 'Discord', @@ -229,7 +229,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'paypalSandbox' => [ 'name' => 'PayPal Sandbox', @@ -239,7 +239,7 @@ return [ // Ordered by ABC. 'sandbox' => true, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'podio' => [ 'name' => 'Podio', @@ -289,7 +289,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'tradeshift' => [ 'name' => 'Tradeshift', @@ -329,7 +329,7 @@ return [ // Ordered by ABC. 'sandbox' => false, 'form' => false, 'beta' => false, - 'mock' => false, + 'mock' => false ], 'yahoo' => [ 'name' => 'Yahoo', diff --git a/app/config/avatars/browsers.php b/app/config/avatars/browsers.php index 7d80937bd3..e7d31c7443 100644 --- a/app/config/avatars/browsers.php +++ b/app/config/avatars/browsers.php @@ -2,20 +2,21 @@ return [ // Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php - 'aa' => ['name' => 'Avant Browser', 'path' => __DIR__.'/browsers/avant.png'], - 'an' => ['name' => 'Android WebView Beta', 'path' => __DIR__.'/browsers/android-webview-beta.png'], - 'ch' => ['name' => 'Google Chrome', 'path' => __DIR__.'/browsers/chrome.png'], - 'ci' => ['name' => 'Google Chrome (iOS)', 'path' => __DIR__.'/browsers/chrome.png'], - 'cm' => ['name' => 'Google Chrome (Mobile)', 'path' => __DIR__.'/browsers/chrome.png'], - 'cr' => ['name' => 'Chromium', 'path' => __DIR__.'/browsers/chromium.png'], - 'ff' => ['name' => 'Mozilla Firefox', 'path' => __DIR__.'/browsers/firefox.png'], - 'sf' => ['name' => 'Safari', 'path' => __DIR__.'/browsers/safari.png'], - 'mf' => ['name' => 'Mobile Safari', 'path' => __DIR__.'/browsers/safari.png'], - 'ps' => ['name' => 'Microsoft Edge', 'path' => __DIR__.'/browsers/edge.png'], - 'oi' => ['name' => 'Microsoft Edge (iOS)', 'path' => __DIR__.'/browsers/edge.png'], - 'om' => ['name' => 'Opera Mini', 'path' => __DIR__.'/browsers/opera-mini.png'], - 'op' => ['name' => 'Opera', 'path' => __DIR__.'/browsers/opera.png'], - 'on' => ['name' => 'Opera (Next)', 'path' => __DIR__.'/browsers/opera.png'], + 'aa' => ['name' => 'Avant Browser', 'path' => __DIR__ . '/browsers/avant.png'], + 'an' => ['name' => 'Android WebView Beta', 'path' => __DIR__ . '/browsers/android-webview-beta.png'], + 'ch' => ['name' => 'Google Chrome', 'path' => __DIR__ . '/browsers/chrome.png'], + 'ci' => ['name' => 'Google Chrome (iOS)', 'path' => __DIR__ . '/browsers/chrome.png'], + 'cm' => ['name' => 'Google Chrome (Mobile)', 'path' => __DIR__ . '/browsers/chrome.png'], + 'cr' => ['name' => 'Chromium', 'path' => __DIR__ . '/browsers/chromium.png'], + 'ff' => ['name' => 'Mozilla Firefox', 'path' => __DIR__ . '/browsers/firefox.png'], + 'sf' => ['name' => 'Safari', 'path' => __DIR__ . '/browsers/safari.png'], + 'mf' => ['name' => 'Mobile Safari', 'path' => __DIR__ . '/browsers/safari.png'], + 'ps' => ['name' => 'Microsoft Edge', 'path' => __DIR__ . '/browsers/edge.png'], + 'oi' => ['name' => 'Microsoft Edge (iOS)', 'path' => __DIR__ . '/browsers/edge.png'], + 'om' => ['name' => 'Opera Mini', 'path' => __DIR__ . '/browsers/opera-mini.png'], + 'op' => ['name' => 'Opera', 'path' => __DIR__ . '/browsers/opera.png'], + 'on' => ['name' => 'Opera (Next)', 'path' => __DIR__ . '/browsers/opera.png'], + /* '36' => '360 Phone Browser', diff --git a/app/config/avatars/credit-cards.php b/app/config/avatars/credit-cards.php index 0655c6fcda..aaef17ee3f 100644 --- a/app/config/avatars/credit-cards.php +++ b/app/config/avatars/credit-cards.php @@ -1,20 +1,20 @@ ['name' => 'American Express', 'path' => __DIR__.'/credit-cards/amex.png'], - 'argencard' => ['name' => 'Argencard', 'path' => __DIR__.'/credit-cards/argencard.png'], - 'cabal' => ['name' => 'Cabal', 'path' => __DIR__.'/credit-cards/cabal.png'], - 'censosud' => ['name' => 'Consosud', 'path' => __DIR__.'/credit-cards/consosud.png'], - 'diners' => ['name' => 'Diners Club', 'path' => __DIR__.'/credit-cards/diners.png'], - 'discover' => ['name' => 'Discover', 'path' => __DIR__.'/credit-cards/discover.png'], - 'elo' => ['name' => 'Elo', 'path' => __DIR__.'/credit-cards/elo.png'], - 'hipercard' => ['name' => 'Hipercard', 'path' => __DIR__.'/credit-cards/hipercard.png'], - 'jcb' => ['name' => 'JCB', 'path' => __DIR__.'/credit-cards/jcb.png'], - 'mastercard' => ['name' => 'Mastercard', 'path' => __DIR__.'/credit-cards/mastercard.png'], - 'naranja' => ['name' => 'Naranja', 'path' => __DIR__.'/credit-cards/naranja.png'], - 'targeta-shopping' => ['name' => 'Tarjeta Shopping', 'path' => __DIR__.'/credit-cards/tarjeta-shopping.png'], - 'union-china-pay' => ['name' => 'Union China Pay', 'path' => __DIR__.'/credit-cards/union-china-pay.png'], - 'visa' => ['name' => 'Visa', 'path' => __DIR__.'/credit-cards/visa.png'], - 'mir' => ['name' => 'MIR', 'path' => __DIR__.'/credit-cards/mir.png'], - 'maestro' => ['name' => 'Maestro', 'path' => __DIR__.'/credit-cards/maestro.png'], -]; + 'amex' => ['name' => 'American Express', 'path' => __DIR__ . '/credit-cards/amex.png'], + 'argencard' => ['name' => 'Argencard', 'path' => __DIR__ . '/credit-cards/argencard.png'], + 'cabal' => ['name' => 'Cabal', 'path' => __DIR__ . '/credit-cards/cabal.png'], + 'censosud' => ['name' => 'Consosud', 'path' => __DIR__ . '/credit-cards/consosud.png'], + 'diners' => ['name' => 'Diners Club', 'path' => __DIR__ . '/credit-cards/diners.png'], + 'discover' => ['name' => 'Discover', 'path' => __DIR__ . '/credit-cards/discover.png'], + 'elo' => ['name' => 'Elo', 'path' => __DIR__ . '/credit-cards/elo.png'], + 'hipercard' => ['name' => 'Hipercard', 'path' => __DIR__ . '/credit-cards/hipercard.png'], + 'jcb' => ['name' => 'JCB', 'path' => __DIR__ . '/credit-cards/jcb.png'], + 'mastercard' => ['name' => 'Mastercard', 'path' => __DIR__ . '/credit-cards/mastercard.png'], + 'naranja' => ['name' => 'Naranja', 'path' => __DIR__ . '/credit-cards/naranja.png'], + 'targeta-shopping' => ['name' => 'Tarjeta Shopping', 'path' => __DIR__ . '/credit-cards/tarjeta-shopping.png'], + 'union-china-pay' => ['name' => 'Union China Pay', 'path' => __DIR__ . '/credit-cards/union-china-pay.png'], + 'visa' => ['name' => 'Visa', 'path' => __DIR__ . '/credit-cards/visa.png'], + 'mir' => ['name' => 'MIR', 'path' => __DIR__ . '/credit-cards/mir.png'], + 'maestro' => ['name' => 'Maestro', 'path' => __DIR__ . '/credit-cards/maestro.png'] + ]; diff --git a/app/config/avatars/flags.php b/app/config/avatars/flags.php index 144a8bfd31..696656738e 100644 --- a/app/config/avatars/flags.php +++ b/app/config/avatars/flags.php @@ -1,198 +1,198 @@ ['name' => 'Afghanistan', 'path' => __DIR__.'/flags/af.png'], - 'ao' => ['name' => 'Angola', 'path' => __DIR__.'/flags/ao.png'], - 'al' => ['name' => 'Albania', 'path' => __DIR__.'/flags/al.png'], - 'ad' => ['name' => 'Andorra', 'path' => __DIR__.'/flags/ad.png'], - 'ae' => ['name' => 'United Arab Emirates', 'path' => __DIR__.'/flags/ae.png'], - 'ar' => ['name' => 'Argentina', 'path' => __DIR__.'/flags/ar.png'], - 'am' => ['name' => 'Armenia', 'path' => __DIR__.'/flags/am.png'], - 'ag' => ['name' => 'Antigua and Barbuda', 'path' => __DIR__.'/flags/ag.png'], - 'au' => ['name' => 'Australia', 'path' => __DIR__.'/flags/au.png'], - 'at' => ['name' => 'Austria', 'path' => __DIR__.'/flags/at.png'], - 'az' => ['name' => 'Azerbaijan', 'path' => __DIR__.'/flags/az.png'], - 'bi' => ['name' => 'Burundi', 'path' => __DIR__.'/flags/bi.png'], - 'be' => ['name' => 'Belgium', 'path' => __DIR__.'/flags/be.png'], - 'bj' => ['name' => 'Benin', 'path' => __DIR__.'/flags/bj.png'], - 'bf' => ['name' => 'Burkina Faso', 'path' => __DIR__.'/flags/bf.png'], - 'bd' => ['name' => 'Bangladesh', 'path' => __DIR__.'/flags/bd.png'], - 'bg' => ['name' => 'Bulgaria', 'path' => __DIR__.'/flags/bg.png'], - 'bh' => ['name' => 'Bahrain', 'path' => __DIR__.'/flags/bh.png'], - 'bs' => ['name' => 'Bahamas', 'path' => __DIR__.'/flags/bs.png'], - 'ba' => ['name' => 'Bosnia and Herzegovina', 'path' => __DIR__.'/flags/ba.png'], - 'by' => ['name' => 'Belarus', 'path' => __DIR__.'/flags/by.png'], - 'bz' => ['name' => 'Belize', 'path' => __DIR__.'/flags/bz.png'], - 'bo' => ['name' => 'Bolivia', 'path' => __DIR__.'/flags/bo.png'], - 'br' => ['name' => 'Brazil', 'path' => __DIR__.'/flags/br.png'], - 'bb' => ['name' => 'Barbados', 'path' => __DIR__.'/flags/bb.png'], - 'bn' => ['name' => 'Brunei Darussalam', 'path' => __DIR__.'/flags/bn.png'], - 'bt' => ['name' => 'Bhutan', 'path' => __DIR__.'/flags/bt.png'], - 'bw' => ['name' => 'Botswana', 'path' => __DIR__.'/flags/bw.png'], - 'cf' => ['name' => 'Central African Republic', 'path' => __DIR__.'/flags/cf.png'], - 'ca' => ['name' => 'Canada', 'path' => __DIR__.'/flags/ca.png'], - 'ch' => ['name' => 'Switzerland', 'path' => __DIR__.'/flags/ch.png'], - 'cl' => ['name' => 'Chile', 'path' => __DIR__.'/flags/cl.png'], - 'cn' => ['name' => 'China', 'path' => __DIR__.'/flags/cn.png'], - 'ci' => ['name' => 'Côte d\'Ivoire', 'path' => __DIR__.'/flags/ci.png'], - 'cm' => ['name' => 'Cameroon', 'path' => __DIR__.'/flags/cm.png'], - 'cd' => ['name' => 'Democratic Republic of the Congo', 'path' => __DIR__.'/flags/cd.png'], - 'cg' => ['name' => 'Republic of the Congo', 'path' => __DIR__.'/flags/cg.png'], - 'co' => ['name' => 'Colombia', 'path' => __DIR__.'/flags/co.png'], - 'km' => ['name' => 'Comoros', 'path' => __DIR__.'/flags/km.png'], - 'cv' => ['name' => 'Cape Verde', 'path' => __DIR__.'/flags/cv.png'], - 'cr' => ['name' => 'Costa Rica', 'path' => __DIR__.'/flags/cr.png'], - 'cu' => ['name' => 'Cuba', 'path' => __DIR__.'/flags/cu.png'], - 'cy' => ['name' => 'Cyprus', 'path' => __DIR__.'/flags/cy.png'], - 'cz' => ['name' => 'Czech Republic', 'path' => __DIR__.'/flags/cz.png'], - 'de' => ['name' => 'Germany', 'path' => __DIR__.'/flags/de.png'], - 'dj' => ['name' => 'Djibouti', 'path' => __DIR__.'/flags/dj.png'], - 'dm' => ['name' => 'Dominica', 'path' => __DIR__.'/flags/dm.png'], - 'dk' => ['name' => 'Denmark', 'path' => __DIR__.'/flags/dk.png'], - 'do' => ['name' => 'Dominican Republic', 'path' => __DIR__.'/flags/do.png'], - 'dz' => ['name' => 'Algeria', 'path' => __DIR__.'/flags/dz.png'], - 'ec' => ['name' => 'Ecuador', 'path' => __DIR__.'/flags/ec.png'], - 'eg' => ['name' => 'Egypt', 'path' => __DIR__.'/flags/eg.png'], - 'er' => ['name' => 'Eritrea', 'path' => __DIR__.'/flags/er.png'], - 'es' => ['name' => 'Spain', 'path' => __DIR__.'/flags/es.png'], - 'ee' => ['name' => 'Estonia', 'path' => __DIR__.'/flags/ee.png'], - 'et' => ['name' => 'Ethiopia', 'path' => __DIR__.'/flags/et.png'], - 'fi' => ['name' => 'Finland', 'path' => __DIR__.'/flags/fi.png'], - 'fj' => ['name' => 'Fiji', 'path' => __DIR__.'/flags/fj.png'], - 'fr' => ['name' => 'France', 'path' => __DIR__.'/flags/fr.png'], - 'fm' => ['name' => 'Micronesia (Federated States of)', 'path' => __DIR__.'/flags/fm.png'], - 'ga' => ['name' => 'Gabon', 'path' => __DIR__.'/flags/ga.png'], - 'gb' => ['name' => 'United Kingdom', 'path' => __DIR__.'/flags/gb.png'], - 'ge' => ['name' => 'Georgia', 'path' => __DIR__.'/flags/ge.png'], - 'gh' => ['name' => 'Ghana', 'path' => __DIR__.'/flags/gh.png'], - 'gn' => ['name' => 'Guinea', 'path' => __DIR__.'/flags/gn.png'], - 'gm' => ['name' => 'Gambia', 'path' => __DIR__.'/flags/gm.png'], - 'gw' => ['name' => 'Guinea-Bissau', 'path' => __DIR__.'/flags/gw.png'], - 'gq' => ['name' => 'Equatorial Guinea', 'path' => __DIR__.'/flags/gq.png'], - 'gr' => ['name' => 'Greece', 'path' => __DIR__.'/flags/gr.png'], - 'gd' => ['name' => 'Grenada', 'path' => __DIR__.'/flags/gd.png'], - 'gt' => ['name' => 'Guatemala', 'path' => __DIR__.'/flags/gt.png'], - 'gy' => ['name' => 'Guyana', 'path' => __DIR__.'/flags/gy.png'], - 'hn' => ['name' => 'Honduras', 'path' => __DIR__.'/flags/hn.png'], - 'hr' => ['name' => 'Croatia', 'path' => __DIR__.'/flags/hr.png'], - 'ht' => ['name' => 'Haiti', 'path' => __DIR__.'/flags/ht.png'], - 'hu' => ['name' => 'Hungary', 'path' => __DIR__.'/flags/hu.png'], - 'id' => ['name' => 'Indonesia', 'path' => __DIR__.'/flags/id.png'], - 'in' => ['name' => 'India', 'path' => __DIR__.'/flags/in.png'], - 'ie' => ['name' => 'Ireland', 'path' => __DIR__.'/flags/ie.png'], - 'ir' => ['name' => 'Iran (Islamic Republic of)', 'path' => __DIR__.'/flags/ir.png'], - 'iq' => ['name' => 'Iraq', 'path' => __DIR__.'/flags/iq.png'], - 'is' => ['name' => 'Iceland', 'path' => __DIR__.'/flags/is.png'], - 'il' => ['name' => 'Israel', 'path' => __DIR__.'/flags/il.png'], - 'it' => ['name' => 'Italy', 'path' => __DIR__.'/flags/it.png'], - 'jm' => ['name' => 'Jamaica', 'path' => __DIR__.'/flags/jm.png'], - 'jo' => ['name' => 'Jordan', 'path' => __DIR__.'/flags/jo.png'], - 'jp' => ['name' => 'Japan', 'path' => __DIR__.'/flags/jp.png'], - 'kz' => ['name' => 'Kazakhstan', 'path' => __DIR__.'/flags/kz.png'], - 'ke' => ['name' => 'Kenya', 'path' => __DIR__.'/flags/ke.png'], - 'kg' => ['name' => 'Kyrgyzstan', 'path' => __DIR__.'/flags/kg.png'], - 'kh' => ['name' => 'Cambodia', 'path' => __DIR__.'/flags/kh.png'], - 'ki' => ['name' => 'Kiribati', 'path' => __DIR__.'/flags/ki.png'], - 'kn' => ['name' => 'Saint Kitts and Nevis', 'path' => __DIR__.'/flags/kn.png'], - 'kr' => ['name' => 'South Korea', 'path' => __DIR__.'/flags/kr.png'], - 'kw' => ['name' => 'Kuwait', 'path' => __DIR__.'/flags/kw.png'], - 'la' => ['name' => 'Lao People\'s Democratic Republic', 'path' => __DIR__.'/flags/la.png'], - 'lb' => ['name' => 'Lebanon', 'path' => __DIR__.'/flags/lb.png'], - 'lr' => ['name' => 'Liberia', 'path' => __DIR__.'/flags/lr.png'], - 'ly' => ['name' => 'Libya', 'path' => __DIR__.'/flags/ly.png'], - 'lc' => ['name' => 'Saint Lucia', 'path' => __DIR__.'/flags/lc.png'], - 'li' => ['name' => 'Liechtenstein', 'path' => __DIR__.'/flags/li.png'], - 'lk' => ['name' => 'Sri Lanka', 'path' => __DIR__.'/flags/lk.png'], - 'ls' => ['name' => 'Lesotho', 'path' => __DIR__.'/flags/ls.png'], - 'lt' => ['name' => 'Lithuania', 'path' => __DIR__.'/flags/lt.png'], - 'lu' => ['name' => 'Luxembourg', 'path' => __DIR__.'/flags/lu.png'], - 'lv' => ['name' => 'Latvia', 'path' => __DIR__.'/flags/lv.png'], - 'ma' => ['name' => 'Morocco', 'path' => __DIR__.'/flags/ma.png'], - 'mc' => ['name' => 'Monaco', 'path' => __DIR__.'/flags/mc.png'], - 'md' => ['name' => 'Moldova', 'path' => __DIR__.'/flags/md.png'], - 'mg' => ['name' => 'Madagascar', 'path' => __DIR__.'/flags/mg.png'], - 'mv' => ['name' => 'Maldives', 'path' => __DIR__.'/flags/mv.png'], - 'mx' => ['name' => 'Mexico', 'path' => __DIR__.'/flags/mx.png'], - 'mh' => ['name' => 'Marshall Islands', 'path' => __DIR__.'/flags/mh.png'], - 'mk' => ['name' => 'North Macedonia', 'path' => __DIR__.'/flags/mk.png'], - 'ml' => ['name' => 'Mali', 'path' => __DIR__.'/flags/ml.png'], - 'mt' => ['name' => 'Malta', 'path' => __DIR__.'/flags/mt.png'], - 'mm' => ['name' => 'Myanmar', 'path' => __DIR__.'/flags/mm.png'], - 'me' => ['name' => 'Montenegro', 'path' => __DIR__.'/flags/me.png'], - 'mn' => ['name' => 'Mongolia', 'path' => __DIR__.'/flags/mn.png'], - 'mz' => ['name' => 'Mozambique', 'path' => __DIR__.'/flags/mz.png'], - 'mr' => ['name' => 'Mauritania', 'path' => __DIR__.'/flags/mr.png'], - 'mu' => ['name' => 'Mauritius', 'path' => __DIR__.'/flags/mu.png'], - 'mw' => ['name' => 'Malawi', 'path' => __DIR__.'/flags/mw.png'], - 'my' => ['name' => 'Malaysia', 'path' => __DIR__.'/flags/my.png'], - 'na' => ['name' => 'Namibia', 'path' => __DIR__.'/flags/na.png'], - 'ne' => ['name' => 'Niger', 'path' => __DIR__.'/flags/ne.png'], - 'ng' => ['name' => 'Nigeria', 'path' => __DIR__.'/flags/ng.png'], - 'ni' => ['name' => 'Nicaragua', 'path' => __DIR__.'/flags/ni.png'], - 'nl' => ['name' => 'Netherlands', 'path' => __DIR__.'/flags/nl.png'], - 'no' => ['name' => 'Norway', 'path' => __DIR__.'/flags/no.png'], - 'np' => ['name' => 'Nepal', 'path' => __DIR__.'/flags/np.png'], - 'nr' => ['name' => 'Nauru', 'path' => __DIR__.'/flags/nr.png'], - 'nz' => ['name' => 'New Zealand', 'path' => __DIR__.'/flags/nz.png'], - 'om' => ['name' => 'Oman', 'path' => __DIR__.'/flags/om.png'], - 'pk' => ['name' => 'Pakistan', 'path' => __DIR__.'/flags/pk.png'], - 'pa' => ['name' => 'Panama', 'path' => __DIR__.'/flags/pa.png'], - 'pe' => ['name' => 'Peru', 'path' => __DIR__.'/flags/pe.png'], - 'ph' => ['name' => 'Philippines', 'path' => __DIR__.'/flags/ph.png'], - 'pw' => ['name' => 'Palau', 'path' => __DIR__.'/flags/pw.png'], - 'pg' => ['name' => 'Papua New Guinea', 'path' => __DIR__.'/flags/pg.png'], - 'pl' => ['name' => 'Poland', 'path' => __DIR__.'/flags/pl.png'], - 'kp' => ['name' => 'North Korea', 'path' => __DIR__.'/flags/kp.png'], - 'pt' => ['name' => 'Portugal', 'path' => __DIR__.'/flags/pt.png'], - 'py' => ['name' => 'Paraguay', 'path' => __DIR__.'/flags/py.png'], - 'qa' => ['name' => 'Qatar', 'path' => __DIR__.'/flags/qa.png'], - 'ro' => ['name' => 'Romania', 'path' => __DIR__.'/flags/ro.png'], - 'ru' => ['name' => 'Russia', 'path' => __DIR__.'/flags/ru.png'], - 'rw' => ['name' => 'Rwanda', 'path' => __DIR__.'/flags/rw.png'], - 'sa' => ['name' => 'Saudi Arabia', 'path' => __DIR__.'/flags/sa.png'], - 'sd' => ['name' => 'Sudan', 'path' => __DIR__.'/flags/sd.png'], - 'sn' => ['name' => 'Senegal', 'path' => __DIR__.'/flags/sn.png'], - 'sg' => ['name' => 'Singapore', 'path' => __DIR__.'/flags/sg.png'], - 'sb' => ['name' => 'Solomon Islands', 'path' => __DIR__.'/flags/sb.png'], - 'sl' => ['name' => 'Sierra Leone', 'path' => __DIR__.'/flags/sl.png'], - 'sv' => ['name' => 'El Salvador', 'path' => __DIR__.'/flags/sv.png'], - 'sm' => ['name' => 'San Marino', 'path' => __DIR__.'/flags/sm.png'], - 'so' => ['name' => 'Somalia', 'path' => __DIR__.'/flags/so.png'], - 'rs' => ['name' => 'Serbia', 'path' => __DIR__.'/flags/rs.png'], - 'ss' => ['name' => 'South Sudan', 'path' => __DIR__.'/flags/ss.png'], - 'st' => ['name' => 'Sao Tome and Principe', 'path' => __DIR__.'/flags/st.png'], - 'sr' => ['name' => 'Suriname', 'path' => __DIR__.'/flags/sr.png'], - 'sk' => ['name' => 'Slovakia', 'path' => __DIR__.'/flags/sk.png'], - 'si' => ['name' => 'Slovenia', 'path' => __DIR__.'/flags/si.png'], - 'se' => ['name' => 'Sweden', 'path' => __DIR__.'/flags/se.png'], - 'sz' => ['name' => 'Eswatini', 'path' => __DIR__.'/flags/sz.png'], - 'sc' => ['name' => 'Seychelles', 'path' => __DIR__.'/flags/sc.png'], - 'sy' => ['name' => 'Syria', 'path' => __DIR__.'/flags/sy.png'], - 'td' => ['name' => 'Chad', 'path' => __DIR__.'/flags/td.png'], - 'tg' => ['name' => 'Togo', 'path' => __DIR__.'/flags/tg.png'], - 'th' => ['name' => 'Thailand', 'path' => __DIR__.'/flags/th.png'], - 'tj' => ['name' => 'Tajikistan', 'path' => __DIR__.'/flags/tj.png'], - 'tm' => ['name' => 'Turkmenistan', 'path' => __DIR__.'/flags/tm.png'], - 'tl' => ['name' => 'Timor-Leste', 'path' => __DIR__.'/flags/tl.png'], - 'to' => ['name' => 'Tonga', 'path' => __DIR__.'/flags/to.png'], - 'tt' => ['name' => 'Trinidad and Tobago', 'path' => __DIR__.'/flags/tt.png'], - 'tn' => ['name' => 'Tunisia', 'path' => __DIR__.'/flags/tn.png'], - 'tr' => ['name' => 'Turkey', 'path' => __DIR__.'/flags/tr.png'], - 'tv' => ['name' => 'Tuvalu', 'path' => __DIR__.'/flags/tv.png'], - 'tz' => ['name' => 'Tanzania', 'path' => __DIR__.'/flags/tz.png'], - 'ug' => ['name' => 'Uganda', 'path' => __DIR__.'/flags/ug.png'], - 'ua' => ['name' => 'Ukraine', 'path' => __DIR__.'/flags/ua.png'], - 'uy' => ['name' => 'Uruguay', 'path' => __DIR__.'/flags/uy.png'], - 'us' => ['name' => 'United States', 'path' => __DIR__.'/flags/us.png'], - 'uz' => ['name' => 'Uzbekistan', 'path' => __DIR__.'/flags/uz.png'], - 'va' => ['name' => 'Vatican City', 'path' => __DIR__.'/flags/va.png'], - 'vc' => ['name' => 'Saint Vincent and the Grenadines', 'path' => __DIR__.'/flags/vc.png'], - 've' => ['name' => 'Venezuela', 'path' => __DIR__.'/flags/ve.png'], - 'vn' => ['name' => 'Vietnam', 'path' => __DIR__.'/flags/vn.png'], - 'vu' => ['name' => 'Vanuatu', 'path' => __DIR__.'/flags/vu.png'], - 'ws' => ['name' => 'Samoa', 'path' => __DIR__.'/flags/ws.png'], - 'ye' => ['name' => 'Yemen', 'path' => __DIR__.'/flags/ye.png'], - 'za' => ['name' => 'South Africa', 'path' => __DIR__.'/flags/za.png'], - 'zm' => ['name' => 'Zambia', 'path' => __DIR__.'/flags/zm.png'], - 'zw' => ['name' => 'Zimbabwe', 'path' => __DIR__.'/flags/zw.png'], + 'af' => ['name' => 'Afghanistan', 'path' => __DIR__ . '/flags/af.png'], + 'ao' => ['name' => 'Angola', 'path' => __DIR__ . '/flags/ao.png'], + 'al' => ['name' => 'Albania', 'path' => __DIR__ . '/flags/al.png'], + 'ad' => ['name' => 'Andorra', 'path' => __DIR__ . '/flags/ad.png'], + 'ae' => ['name' => 'United Arab Emirates', 'path' => __DIR__ . '/flags/ae.png'], + 'ar' => ['name' => 'Argentina', 'path' => __DIR__ . '/flags/ar.png'], + 'am' => ['name' => 'Armenia', 'path' => __DIR__ . '/flags/am.png'], + 'ag' => ['name' => 'Antigua and Barbuda', 'path' => __DIR__ . '/flags/ag.png'], + 'au' => ['name' => 'Australia', 'path' => __DIR__ . '/flags/au.png'], + 'at' => ['name' => 'Austria', 'path' => __DIR__ . '/flags/at.png'], + 'az' => ['name' => 'Azerbaijan', 'path' => __DIR__ . '/flags/az.png'], + 'bi' => ['name' => 'Burundi', 'path' => __DIR__ . '/flags/bi.png'], + 'be' => ['name' => 'Belgium', 'path' => __DIR__ . '/flags/be.png'], + 'bj' => ['name' => 'Benin', 'path' => __DIR__ . '/flags/bj.png'], + 'bf' => ['name' => 'Burkina Faso', 'path' => __DIR__ . '/flags/bf.png'], + 'bd' => ['name' => 'Bangladesh', 'path' => __DIR__ . '/flags/bd.png'], + 'bg' => ['name' => 'Bulgaria', 'path' => __DIR__ . '/flags/bg.png'], + 'bh' => ['name' => 'Bahrain', 'path' => __DIR__ . '/flags/bh.png'], + 'bs' => ['name' => 'Bahamas', 'path' => __DIR__ . '/flags/bs.png'], + 'ba' => ['name' => 'Bosnia and Herzegovina', 'path' => __DIR__ . '/flags/ba.png'], + 'by' => ['name' => 'Belarus', 'path' => __DIR__ . '/flags/by.png'], + 'bz' => ['name' => 'Belize', 'path' => __DIR__ . '/flags/bz.png'], + 'bo' => ['name' => 'Bolivia', 'path' => __DIR__ . '/flags/bo.png'], + 'br' => ['name' => 'Brazil', 'path' => __DIR__ . '/flags/br.png'], + 'bb' => ['name' => 'Barbados', 'path' => __DIR__ . '/flags/bb.png'], + 'bn' => ['name' => 'Brunei Darussalam', 'path' => __DIR__ . '/flags/bn.png'], + 'bt' => ['name' => 'Bhutan', 'path' => __DIR__ . '/flags/bt.png'], + 'bw' => ['name' => 'Botswana', 'path' => __DIR__ . '/flags/bw.png'], + 'cf' => ['name' => 'Central African Republic', 'path' => __DIR__ . '/flags/cf.png'], + 'ca' => ['name' => 'Canada', 'path' => __DIR__ . '/flags/ca.png'], + 'ch' => ['name' => 'Switzerland', 'path' => __DIR__ . '/flags/ch.png'], + 'cl' => ['name' => 'Chile', 'path' => __DIR__ . '/flags/cl.png'], + 'cn' => ['name' => 'China', 'path' => __DIR__ . '/flags/cn.png'], + 'ci' => ['name' => 'Côte d\'Ivoire', 'path' => __DIR__ . '/flags/ci.png'], + 'cm' => ['name' => 'Cameroon', 'path' => __DIR__ . '/flags/cm.png'], + 'cd' => ['name' => 'Democratic Republic of the Congo', 'path' => __DIR__ . '/flags/cd.png'], + 'cg' => ['name' => 'Republic of the Congo', 'path' => __DIR__ . '/flags/cg.png'], + 'co' => ['name' => 'Colombia', 'path' => __DIR__ . '/flags/co.png'], + 'km' => ['name' => 'Comoros', 'path' => __DIR__ . '/flags/km.png'], + 'cv' => ['name' => 'Cape Verde', 'path' => __DIR__ . '/flags/cv.png'], + 'cr' => ['name' => 'Costa Rica', 'path' => __DIR__ . '/flags/cr.png'], + 'cu' => ['name' => 'Cuba', 'path' => __DIR__ . '/flags/cu.png'], + 'cy' => ['name' => 'Cyprus', 'path' => __DIR__ . '/flags/cy.png'], + 'cz' => ['name' => 'Czech Republic', 'path' => __DIR__ . '/flags/cz.png'], + 'de' => ['name' => 'Germany', 'path' => __DIR__ . '/flags/de.png'], + 'dj' => ['name' => 'Djibouti', 'path' => __DIR__ . '/flags/dj.png'], + 'dm' => ['name' => 'Dominica', 'path' => __DIR__ . '/flags/dm.png'], + 'dk' => ['name' => 'Denmark', 'path' => __DIR__ . '/flags/dk.png'], + 'do' => ['name' => 'Dominican Republic', 'path' => __DIR__ . '/flags/do.png'], + 'dz' => ['name' => 'Algeria', 'path' => __DIR__ . '/flags/dz.png'], + 'ec' => ['name' => 'Ecuador', 'path' => __DIR__ . '/flags/ec.png'], + 'eg' => ['name' => 'Egypt', 'path' => __DIR__ . '/flags/eg.png'], + 'er' => ['name' => 'Eritrea', 'path' => __DIR__ . '/flags/er.png'], + 'es' => ['name' => 'Spain', 'path' => __DIR__ . '/flags/es.png'], + 'ee' => ['name' => 'Estonia', 'path' => __DIR__ . '/flags/ee.png'], + 'et' => ['name' => 'Ethiopia', 'path' => __DIR__ . '/flags/et.png'], + 'fi' => ['name' => 'Finland', 'path' => __DIR__ . '/flags/fi.png'], + 'fj' => ['name' => 'Fiji', 'path' => __DIR__ . '/flags/fj.png'], + 'fr' => ['name' => 'France', 'path' => __DIR__ . '/flags/fr.png'], + 'fm' => ['name' => 'Micronesia (Federated States of)', 'path' => __DIR__ . '/flags/fm.png'], + 'ga' => ['name' => 'Gabon', 'path' => __DIR__ . '/flags/ga.png'], + 'gb' => ['name' => 'United Kingdom', 'path' => __DIR__ . '/flags/gb.png'], + 'ge' => ['name' => 'Georgia', 'path' => __DIR__ . '/flags/ge.png'], + 'gh' => ['name' => 'Ghana', 'path' => __DIR__ . '/flags/gh.png'], + 'gn' => ['name' => 'Guinea', 'path' => __DIR__ . '/flags/gn.png'], + 'gm' => ['name' => 'Gambia', 'path' => __DIR__ . '/flags/gm.png'], + 'gw' => ['name' => 'Guinea-Bissau', 'path' => __DIR__ . '/flags/gw.png'], + 'gq' => ['name' => 'Equatorial Guinea', 'path' => __DIR__ . '/flags/gq.png'], + 'gr' => ['name' => 'Greece', 'path' => __DIR__ . '/flags/gr.png'], + 'gd' => ['name' => 'Grenada', 'path' => __DIR__ . '/flags/gd.png'], + 'gt' => ['name' => 'Guatemala', 'path' => __DIR__ . '/flags/gt.png'], + 'gy' => ['name' => 'Guyana', 'path' => __DIR__ . '/flags/gy.png'], + 'hn' => ['name' => 'Honduras', 'path' => __DIR__ . '/flags/hn.png'], + 'hr' => ['name' => 'Croatia', 'path' => __DIR__ . '/flags/hr.png'], + 'ht' => ['name' => 'Haiti', 'path' => __DIR__ . '/flags/ht.png'], + 'hu' => ['name' => 'Hungary', 'path' => __DIR__ . '/flags/hu.png'], + 'id' => ['name' => 'Indonesia', 'path' => __DIR__ . '/flags/id.png'], + 'in' => ['name' => 'India', 'path' => __DIR__ . '/flags/in.png'], + 'ie' => ['name' => 'Ireland', 'path' => __DIR__ . '/flags/ie.png'], + 'ir' => ['name' => 'Iran (Islamic Republic of)', 'path' => __DIR__ . '/flags/ir.png'], + 'iq' => ['name' => 'Iraq', 'path' => __DIR__ . '/flags/iq.png'], + 'is' => ['name' => 'Iceland', 'path' => __DIR__ . '/flags/is.png'], + 'il' => ['name' => 'Israel', 'path' => __DIR__ . '/flags/il.png'], + 'it' => ['name' => 'Italy', 'path' => __DIR__ . '/flags/it.png'], + 'jm' => ['name' => 'Jamaica', 'path' => __DIR__ . '/flags/jm.png'], + 'jo' => ['name' => 'Jordan', 'path' => __DIR__ . '/flags/jo.png'], + 'jp' => ['name' => 'Japan', 'path' => __DIR__ . '/flags/jp.png'], + 'kz' => ['name' => 'Kazakhstan', 'path' => __DIR__ . '/flags/kz.png'], + 'ke' => ['name' => 'Kenya', 'path' => __DIR__ . '/flags/ke.png'], + 'kg' => ['name' => 'Kyrgyzstan', 'path' => __DIR__ . '/flags/kg.png'], + 'kh' => ['name' => 'Cambodia', 'path' => __DIR__ . '/flags/kh.png'], + 'ki' => ['name' => 'Kiribati', 'path' => __DIR__ . '/flags/ki.png'], + 'kn' => ['name' => 'Saint Kitts and Nevis', 'path' => __DIR__ . '/flags/kn.png'], + 'kr' => ['name' => 'South Korea', 'path' => __DIR__ . '/flags/kr.png'], + 'kw' => ['name' => 'Kuwait', 'path' => __DIR__ . '/flags/kw.png'], + 'la' => ['name' => 'Lao People\'s Democratic Republic', 'path' => __DIR__ . '/flags/la.png'], + 'lb' => ['name' => 'Lebanon', 'path' => __DIR__ . '/flags/lb.png'], + 'lr' => ['name' => 'Liberia', 'path' => __DIR__ . '/flags/lr.png'], + 'ly' => ['name' => 'Libya', 'path' => __DIR__ . '/flags/ly.png'], + 'lc' => ['name' => 'Saint Lucia', 'path' => __DIR__ . '/flags/lc.png'], + 'li' => ['name' => 'Liechtenstein', 'path' => __DIR__ . '/flags/li.png'], + 'lk' => ['name' => 'Sri Lanka', 'path' => __DIR__ . '/flags/lk.png'], + 'ls' => ['name' => 'Lesotho', 'path' => __DIR__ . '/flags/ls.png'], + 'lt' => ['name' => 'Lithuania', 'path' => __DIR__ . '/flags/lt.png'], + 'lu' => ['name' => 'Luxembourg', 'path' => __DIR__ . '/flags/lu.png'], + 'lv' => ['name' => 'Latvia', 'path' => __DIR__ . '/flags/lv.png'], + 'ma' => ['name' => 'Morocco', 'path' => __DIR__ . '/flags/ma.png'], + 'mc' => ['name' => 'Monaco', 'path' => __DIR__ . '/flags/mc.png'], + 'md' => ['name' => 'Moldova', 'path' => __DIR__ . '/flags/md.png'], + 'mg' => ['name' => 'Madagascar', 'path' => __DIR__ . '/flags/mg.png'], + 'mv' => ['name' => 'Maldives', 'path' => __DIR__ . '/flags/mv.png'], + 'mx' => ['name' => 'Mexico', 'path' => __DIR__ . '/flags/mx.png'], + 'mh' => ['name' => 'Marshall Islands', 'path' => __DIR__ . '/flags/mh.png'], + 'mk' => ['name' => 'North Macedonia', 'path' => __DIR__ . '/flags/mk.png'], + 'ml' => ['name' => 'Mali', 'path' => __DIR__ . '/flags/ml.png'], + 'mt' => ['name' => 'Malta', 'path' => __DIR__ . '/flags/mt.png'], + 'mm' => ['name' => 'Myanmar', 'path' => __DIR__ . '/flags/mm.png'], + 'me' => ['name' => 'Montenegro', 'path' => __DIR__ . '/flags/me.png'], + 'mn' => ['name' => 'Mongolia', 'path' => __DIR__ . '/flags/mn.png'], + 'mz' => ['name' => 'Mozambique', 'path' => __DIR__ . '/flags/mz.png'], + 'mr' => ['name' => 'Mauritania', 'path' => __DIR__ . '/flags/mr.png'], + 'mu' => ['name' => 'Mauritius', 'path' => __DIR__ . '/flags/mu.png'], + 'mw' => ['name' => 'Malawi', 'path' => __DIR__ . '/flags/mw.png'], + 'my' => ['name' => 'Malaysia', 'path' => __DIR__ . '/flags/my.png'], + 'na' => ['name' => 'Namibia', 'path' => __DIR__ . '/flags/na.png'], + 'ne' => ['name' => 'Niger', 'path' => __DIR__ . '/flags/ne.png'], + 'ng' => ['name' => 'Nigeria', 'path' => __DIR__ . '/flags/ng.png'], + 'ni' => ['name' => 'Nicaragua', 'path' => __DIR__ . '/flags/ni.png'], + 'nl' => ['name' => 'Netherlands', 'path' => __DIR__ . '/flags/nl.png'], + 'no' => ['name' => 'Norway', 'path' => __DIR__ . '/flags/no.png'], + 'np' => ['name' => 'Nepal', 'path' => __DIR__ . '/flags/np.png'], + 'nr' => ['name' => 'Nauru', 'path' => __DIR__ . '/flags/nr.png'], + 'nz' => ['name' => 'New Zealand', 'path' => __DIR__ . '/flags/nz.png'], + 'om' => ['name' => 'Oman', 'path' => __DIR__ . '/flags/om.png'], + 'pk' => ['name' => 'Pakistan', 'path' => __DIR__ . '/flags/pk.png'], + 'pa' => ['name' => 'Panama', 'path' => __DIR__ . '/flags/pa.png'], + 'pe' => ['name' => 'Peru', 'path' => __DIR__ . '/flags/pe.png'], + 'ph' => ['name' => 'Philippines', 'path' => __DIR__ . '/flags/ph.png'], + 'pw' => ['name' => 'Palau', 'path' => __DIR__ . '/flags/pw.png'], + 'pg' => ['name' => 'Papua New Guinea', 'path' => __DIR__ . '/flags/pg.png'], + 'pl' => ['name' => 'Poland', 'path' => __DIR__ . '/flags/pl.png'], + 'kp' => ['name' => 'North Korea', 'path' => __DIR__ . '/flags/kp.png'], + 'pt' => ['name' => 'Portugal', 'path' => __DIR__ . '/flags/pt.png'], + 'py' => ['name' => 'Paraguay', 'path' => __DIR__ . '/flags/py.png'], + 'qa' => ['name' => 'Qatar', 'path' => __DIR__ . '/flags/qa.png'], + 'ro' => ['name' => 'Romania', 'path' => __DIR__ . '/flags/ro.png'], + 'ru' => ['name' => 'Russia', 'path' => __DIR__ . '/flags/ru.png'], + 'rw' => ['name' => 'Rwanda', 'path' => __DIR__ . '/flags/rw.png'], + 'sa' => ['name' => 'Saudi Arabia', 'path' => __DIR__ . '/flags/sa.png'], + 'sd' => ['name' => 'Sudan', 'path' => __DIR__ . '/flags/sd.png'], + 'sn' => ['name' => 'Senegal', 'path' => __DIR__ . '/flags/sn.png'], + 'sg' => ['name' => 'Singapore', 'path' => __DIR__ . '/flags/sg.png'], + 'sb' => ['name' => 'Solomon Islands', 'path' => __DIR__ . '/flags/sb.png'], + 'sl' => ['name' => 'Sierra Leone', 'path' => __DIR__ . '/flags/sl.png'], + 'sv' => ['name' => 'El Salvador', 'path' => __DIR__ . '/flags/sv.png'], + 'sm' => ['name' => 'San Marino', 'path' => __DIR__ . '/flags/sm.png'], + 'so' => ['name' => 'Somalia', 'path' => __DIR__ . '/flags/so.png'], + 'rs' => ['name' => 'Serbia', 'path' => __DIR__ . '/flags/rs.png'], + 'ss' => ['name' => 'South Sudan', 'path' => __DIR__ . '/flags/ss.png'], + 'st' => ['name' => 'Sao Tome and Principe', 'path' => __DIR__ . '/flags/st.png'], + 'sr' => ['name' => 'Suriname', 'path' => __DIR__ . '/flags/sr.png'], + 'sk' => ['name' => 'Slovakia', 'path' => __DIR__ . '/flags/sk.png'], + 'si' => ['name' => 'Slovenia', 'path' => __DIR__ . '/flags/si.png'], + 'se' => ['name' => 'Sweden', 'path' => __DIR__ . '/flags/se.png'], + 'sz' => ['name' => 'Eswatini', 'path' => __DIR__ . '/flags/sz.png'], + 'sc' => ['name' => 'Seychelles', 'path' => __DIR__ . '/flags/sc.png'], + 'sy' => ['name' => 'Syria', 'path' => __DIR__ . '/flags/sy.png'], + 'td' => ['name' => 'Chad', 'path' => __DIR__ . '/flags/td.png'], + 'tg' => ['name' => 'Togo', 'path' => __DIR__ . '/flags/tg.png'], + 'th' => ['name' => 'Thailand', 'path' => __DIR__ . '/flags/th.png'], + 'tj' => ['name' => 'Tajikistan', 'path' => __DIR__ . '/flags/tj.png'], + 'tm' => ['name' => 'Turkmenistan', 'path' => __DIR__ . '/flags/tm.png'], + 'tl' => ['name' => 'Timor-Leste', 'path' => __DIR__ . '/flags/tl.png'], + 'to' => ['name' => 'Tonga', 'path' => __DIR__ . '/flags/to.png'], + 'tt' => ['name' => 'Trinidad and Tobago', 'path' => __DIR__ . '/flags/tt.png'], + 'tn' => ['name' => 'Tunisia', 'path' => __DIR__ . '/flags/tn.png'], + 'tr' => ['name' => 'Turkey', 'path' => __DIR__ . '/flags/tr.png'], + 'tv' => ['name' => 'Tuvalu', 'path' => __DIR__ . '/flags/tv.png'], + 'tz' => ['name' => 'Tanzania', 'path' => __DIR__ . '/flags/tz.png'], + 'ug' => ['name' => 'Uganda', 'path' => __DIR__ . '/flags/ug.png'], + 'ua' => ['name' => 'Ukraine', 'path' => __DIR__ . '/flags/ua.png'], + 'uy' => ['name' => 'Uruguay', 'path' => __DIR__ . '/flags/uy.png'], + 'us' => ['name' => 'United States', 'path' => __DIR__ . '/flags/us.png'], + 'uz' => ['name' => 'Uzbekistan', 'path' => __DIR__ . '/flags/uz.png'], + 'va' => ['name' => 'Vatican City', 'path' => __DIR__ . '/flags/va.png'], + 'vc' => ['name' => 'Saint Vincent and the Grenadines', 'path' => __DIR__ . '/flags/vc.png'], + 've' => ['name' => 'Venezuela', 'path' => __DIR__ . '/flags/ve.png'], + 'vn' => ['name' => 'Vietnam', 'path' => __DIR__ . '/flags/vn.png'], + 'vu' => ['name' => 'Vanuatu', 'path' => __DIR__ . '/flags/vu.png'], + 'ws' => ['name' => 'Samoa', 'path' => __DIR__ . '/flags/ws.png'], + 'ye' => ['name' => 'Yemen', 'path' => __DIR__ . '/flags/ye.png'], + 'za' => ['name' => 'South Africa', 'path' => __DIR__ . '/flags/za.png'], + 'zm' => ['name' => 'Zambia', 'path' => __DIR__ . '/flags/zm.png'], + 'zw' => ['name' => 'Zimbabwe', 'path' => __DIR__ . '/flags/zw.png'], ]; diff --git a/app/config/avatars/os.php b/app/config/avatars/os.php index ba5ee0e1fc..f500eed759 100644 --- a/app/config/avatars/os.php +++ b/app/config/avatars/os.php @@ -2,9 +2,9 @@ return [ // Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php - 'AND' => __DIR__.'/os/android.png', - 'ATV' => __DIR__.'/os/apple-tv.png', - 'COS' => __DIR__.'/os/chrome-os.png', + 'AND' => __DIR__ . '/os/android.png', + 'ATV' => __DIR__ . '/os/apple-tv.png', + 'COS' => __DIR__ . '/os/chrome-os.png', /* 'AIX' => 'AIX', diff --git a/app/config/collections.php b/app/config/collections.php index af68b4174e..c9005f8217 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -16,6 +16,7 @@ $auth = Config::getParam('auth', []); * attributes => list of attributes * indexes => list of indexes */ + $commonCollections = [ 'users' => [ '$collection' => ID::custom(Database::METADATA), @@ -252,7 +253,7 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => ['datetime'], - ], + ] ], 'indexes' => [ [ @@ -409,7 +410,7 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => [], - ], + ] ], 'indexes' => [ [ @@ -1277,7 +1278,7 @@ $commonCollections = [ 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], - ], + ] ], 'stats' => [ @@ -1453,7 +1454,7 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => ['json', 'encrypt'], - ], + ] ], 'indexes' => [ [ @@ -1469,7 +1470,7 @@ $commonCollections = [ 'attributes' => ['name'], 'lengths' => [128], 'orders' => [Database::ORDER_ASC], - ], + ] ], ], @@ -1810,7 +1811,7 @@ $commonCollections = [ 'attributes' => ['topicInternalId'], 'lengths' => [], 'orders' => [], - ], + ] ], ], @@ -1923,7 +1924,7 @@ $commonCollections = [ 'orders' => [], ], ], - ], + ] ]; $projectCollections = array_merge([ @@ -2666,7 +2667,7 @@ $projectCollections = array_merge([ 'default' => false, 'array' => false, 'filters' => [], - ], + ] ], 'indexes' => [ [ @@ -2857,7 +2858,7 @@ $projectCollections = array_merge([ 'default' => '', 'array' => false, 'filters' => [], - ], + ] ], 'indexes' => [ [ @@ -2866,7 +2867,7 @@ $projectCollections = array_merge([ 'attributes' => ['deploymentId'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], - ], + ] ], ], @@ -3101,7 +3102,7 @@ $projectCollections = array_merge([ 'required' => true, 'default' => null, 'array' => false, - 'filters' => ['encrypt'], + 'filters' => [ 'encrypt' ] ], [ '$id' => ID::custom('search'), @@ -3185,7 +3186,7 @@ $projectCollections = array_merge([ 'array' => false, 'filters' => [], ], - ], + ], 'indexes' => [ [ '$id' => '_key_accessedAt', @@ -3307,7 +3308,7 @@ $projectCollections = array_merge([ 'default' => null, 'array' => false, 'filters' => [], - ], + ] ], 'indexes' => [ [ @@ -3337,7 +3338,7 @@ $projectCollections = array_merge([ 'attributes' => ['search'], 'lengths' => [], 'orders' => [], - ], + ] ], ], ], $commonCollections); @@ -3747,7 +3748,7 @@ $consoleCollections = array_merge([ [ '$id' => ID::custom('_key_region_resourceType_resourceUpdatedAt'), 'type' => Database::INDEX_KEY, - 'attributes' => ['region', 'resourceType', 'resourceUpdatedAt'], + 'attributes' => ['region', 'resourceType','resourceUpdatedAt'], 'lengths' => [], 'orders' => [], ], @@ -3842,7 +3843,7 @@ $consoleCollections = array_merge([ 'default' => null, 'array' => false, 'filters' => [], - ], + ] ], 'indexes' => [ [ @@ -4184,7 +4185,7 @@ $consoleCollections = array_merge([ 'attributes' => ['projectInternalId'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], - ], + ] ], ], @@ -4311,7 +4312,7 @@ $consoleCollections = array_merge([ 'default' => null, 'array' => false, 'filters' => [], //TODO: use json filter - ], + ] ], 'indexes' => [ [ @@ -4321,7 +4322,7 @@ $consoleCollections = array_merge([ 'lengths' => [], 'orders' => [Database::ORDER_DESC], ], - ], + ] ], ], $commonCollections); @@ -4587,7 +4588,7 @@ $bucketCollections = [ 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], - ], + ] ], ]; @@ -4710,14 +4711,15 @@ $dbCollections = [ 'orders' => [Database::ORDER_ASC], ], ], - ], + ] ]; + $collections = [ 'projects' => $projectCollections, - 'console' => $consoleCollections, + 'console' => $consoleCollections, 'buckets' => $bucketCollections, - 'databases' => $dbCollections, + 'databases' => $dbCollections ]; return $collections; diff --git a/app/config/errors.php b/app/config/errors.php index 8b11410996..5942c6027c 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -299,7 +299,7 @@ return [ Exception::AVATAR_SET_NOT_FOUND => [ 'name' => Exception::AVATAR_SET_NOT_FOUND, 'description' => 'The requested avatar set could not be found.', - 'code' => 404, + 'code' => 404 ], Exception::AVATAR_NOT_FOUND => [ 'name' => Exception::AVATAR_NOT_FOUND, @@ -426,13 +426,13 @@ return [ Exception::DATABASE_NOT_FOUND => [ 'name' => Exception::DATABASE_NOT_FOUND, 'description' => 'Database not found', - 'code' => 404, + 'code' => 404 ], Exception::DATABASE_ALREADY_EXISTS => [ 'name' => Exception::DATABASE_ALREADY_EXISTS, 'description' => 'Database already exists', - 'code' => 409, + 'code' => 409 ], /** Collections */ @@ -702,5 +702,5 @@ return [ 'name' => Exception::PROVIDER_INCORRECT_TYPE, 'description' => 'Provider with the request ID is of incorrect type: ', 'code' => 400, - ], + ] ]; diff --git a/app/config/events.php b/app/config/events.php index 4ecc651240..45bb45fbf8 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -19,7 +19,7 @@ return [ '$description' => 'This event triggers when a session for a user is created.', ], 'delete' => [ - '$description' => 'This event triggers when a session for a user is deleted.', + '$description' => 'This event triggers when a session for a user is deleted.' ], ], 'recovery' => [ @@ -30,7 +30,7 @@ return [ '$description' => 'This event triggers when a recovery token for a user is created.', ], 'update' => [ - '$description' => 'This event triggers when a recovery token for a user is validated.', + '$description' => 'This event triggers when a recovery token for a user is validated.' ], ], 'verification' => [ @@ -41,7 +41,7 @@ return [ '$description' => 'This event triggers when a verification token for a user is created.', ], 'update' => [ - '$description' => 'This event triggers when a verification token for a user is validated.', + '$description' => 'This event triggers when a verification token for a user is validated.' ], ], 'targets' => [ @@ -59,7 +59,7 @@ return [ ], ], 'create' => [ - '$description' => 'This event triggers when a user is created.', + '$description' => 'This event triggers when a user is created.' ], 'delete' => [ '$description' => 'This event triggers when a user is deleted.', @@ -81,7 +81,7 @@ return [ 'prefs' => [ '$description' => 'This event triggers when a user\'s preferences is updated.', ], - ], + ] ], 'databases' => [ '$model' => Response::MODEL_DATABASE, @@ -99,10 +99,10 @@ return [ '$description' => 'This event triggers when a document is created.', ], 'delete' => [ - '$description' => 'This event triggers when a document is deleted.', + '$description' => 'This event triggers when a document is deleted.' ], 'update' => [ - '$description' => 'This event triggers when a document is updated.', + '$description' => 'This event triggers when a document is updated.' ], ], 'indexes' => [ @@ -113,8 +113,8 @@ return [ '$description' => 'This event triggers when an index is created.', ], 'delete' => [ - '$description' => 'This event triggers when an index is deleted.', - ], + '$description' => 'This event triggers when an index is deleted.' + ] ], 'attributes' => [ '$model' => Response::MODEL_ATTRIBUTE, @@ -124,28 +124,28 @@ return [ '$description' => 'This event triggers when an attribute is created.', ], 'delete' => [ - '$description' => 'This event triggers when an attribute is deleted.', - ], + '$description' => 'This event triggers when an attribute is deleted.' + ] ], 'create' => [ - '$description' => 'This event triggers when a collection is created.', + '$description' => 'This event triggers when a collection is created.' ], 'delete' => [ '$description' => 'This event triggers when a collection is deleted.', ], 'update' => [ '$description' => 'This event triggers when a collection is updated.', - ], + ] ], 'create' => [ - '$description' => 'This event triggers when a database is created.', + '$description' => 'This event triggers when a database is created.' ], 'delete' => [ '$description' => 'This event triggers when a database is deleted.', ], 'update' => [ '$description' => 'This event triggers when a database is updated.', - ], + ] ], 'buckets' => [ '$model' => Response::MODEL_BUCKET, @@ -159,21 +159,21 @@ return [ '$description' => 'This event triggers when a file is created.', ], 'delete' => [ - '$description' => 'This event triggers when a file is deleted.', + '$description' => 'This event triggers when a file is deleted.' ], 'update' => [ - '$description' => 'This event triggers when a file is updated.', + '$description' => 'This event triggers when a file is updated.' ], ], 'create' => [ - '$description' => 'This event triggers when a bucket is created.', + '$description' => 'This event triggers when a bucket is created.' ], 'delete' => [ '$description' => 'This event triggers when a bucket is deleted.', ], 'update' => [ '$description' => 'This event triggers when a bucket is updated.', - ], + ] ], 'teams' => [ '$model' => Response::MODEL_TEAM, @@ -187,17 +187,17 @@ return [ '$description' => 'This event triggers when a membership is created.', ], 'delete' => [ - '$description' => 'This event triggers when a membership is deleted.', + '$description' => 'This event triggers when a membership is deleted.' ], 'update' => [ '$description' => 'This event triggers when a membership is updated.', 'status' => [ - '$description' => 'This event triggers when a team memberships status is updated.', - ], + '$description' => 'This event triggers when a team memberships status is updated.' + ] ], ], 'create' => [ - '$description' => 'This event triggers when a team is created.', + '$description' => 'This event triggers when a team is created.' ], 'delete' => [ '$description' => 'This event triggers when a team is deleted.', @@ -207,7 +207,7 @@ return [ 'prefs' => [ '$description' => 'This event triggers when a team\'s preferences are updated.', ], - ], + ] ], 'functions' => [ '$model' => Response::MODEL_FUNCTION, @@ -221,10 +221,10 @@ return [ '$description' => 'This event triggers when a deployment is created.', ], 'delete' => [ - '$description' => 'This event triggers when a deployment is deleted.', + '$description' => 'This event triggers when a deployment is deleted.' ], 'update' => [ - '$description' => 'This event triggers when a deployment is updated.', + '$description' => 'This event triggers when a deployment is updated.' ], ], 'executions' => [ @@ -235,21 +235,21 @@ return [ '$description' => 'This event triggers when an execution is created.', ], 'delete' => [ - '$description' => 'This event triggers when an execution is deleted.', + '$description' => 'This event triggers when an execution is deleted.' ], 'update' => [ - '$description' => 'This event triggers when an execution is updated.', + '$description' => 'This event triggers when an execution is updated.' ], ], 'create' => [ - '$description' => 'This event triggers when a function is created.', + '$description' => 'This event triggers when a function is created.' ], 'delete' => [ '$description' => 'This event triggers when a function is deleted.', ], 'update' => [ '$description' => 'This event triggers when a function is updated.', - ], + ] ], 'messages' => [ '$model' => Response::MODEL_MESSAGE, @@ -269,7 +269,7 @@ return [ '$description' => 'This event triggers when a provider is updated.', ], 'delete' => [ - '$description' => 'This event triggers when a provider is deleted.', + '$description' => 'This event triggers when a provider is deleted.' ], ], 'topics' => [ @@ -280,7 +280,7 @@ return [ '$description' => 'This event triggers when a provider is created.', ], 'delete' => [ - '$description' => 'This event triggers when a provider is deleted.', + '$description' => 'This event triggers when a provider is deleted.' ], 'subscribers' => [ '$model' => Response::MODEL_SUBSCRIBER, @@ -290,7 +290,7 @@ return [ '$description' => 'This event triggers when a subscriber is created.', ], 'delete' => [ - '$description' => 'This event triggers when a subscriber is deleted.', + '$description' => 'This event triggers when a subscriber is deleted.' ], ], ], diff --git a/app/config/locale/codes.php b/app/config/locale/codes.php index ed878887ca..641a2a6220 100644 --- a/app/config/locale/codes.php +++ b/app/config/locale/codes.php @@ -6,531 +6,532 @@ * * Source: * https://www.andiamo.co.uk/resources/iso-language-codes/ + * */ return [ [ - 'code' => 'af', - 'name' => 'Afrikaans', + "code" => "af", + "name" => "Afrikaans", ], [ - 'code' => 'ar-ae', - 'name' => 'Arabic (U.A.E.)', + "code" => "ar-ae", + "name" => "Arabic (U.A.E.)", ], [ - 'code' => 'ar-bh', - 'name' => 'Arabic (Bahrain)', + "code" => "ar-bh", + "name" => "Arabic (Bahrain)", ], [ - 'code' => 'ar-dz', - 'name' => 'Arabic (Algeria)', + "code" => "ar-dz", + "name" => "Arabic (Algeria)", ], [ - 'code' => 'ar-eg', - 'name' => 'Arabic (Egypt)', + "code" => "ar-eg", + "name" => "Arabic (Egypt)", ], [ - 'code' => 'ar-iq', - 'name' => 'Arabic (Iraq)', + "code" => "ar-iq", + "name" => "Arabic (Iraq)", ], [ - 'code' => 'ar-jo', - 'name' => 'Arabic (Jordan)', + "code" => "ar-jo", + "name" => "Arabic (Jordan)", ], [ - 'code' => 'ar-kw', - 'name' => 'Arabic (Kuwait)', + "code" => "ar-kw", + "name" => "Arabic (Kuwait)", ], [ - 'code' => 'ar-lb', - 'name' => 'Arabic (Lebanon)', + "code" => "ar-lb", + "name" => "Arabic (Lebanon)", ], [ - 'code' => 'ar-ly', - 'name' => 'Arabic (Libya)', + "code" => "ar-ly", + "name" => "Arabic (Libya)", ], [ - 'code' => 'ar-ma', - 'name' => 'Arabic (Morocco)', + "code" => "ar-ma", + "name" => "Arabic (Morocco)", ], [ - 'code' => 'ar-om', - 'name' => 'Arabic (Oman)', + "code" => "ar-om", + "name" => "Arabic (Oman)", ], [ - 'code' => 'ar-qa', - 'name' => 'Arabic (Qatar)', + "code" => "ar-qa", + "name" => "Arabic (Qatar)", ], [ - 'code' => 'ar-sa', - 'name' => 'Arabic (Saudi Arabia)', + "code" => "ar-sa", + "name" => "Arabic (Saudi Arabia)", ], [ - 'code' => 'ar-sy', - 'name' => 'Arabic (Syria)', + "code" => "ar-sy", + "name" => "Arabic (Syria)", ], [ - 'code' => 'ar-tn', - 'name' => 'Arabic (Tunisia)', + "code" => "ar-tn", + "name" => "Arabic (Tunisia)", ], [ - 'code' => 'ar-ye', - 'name' => 'Arabic (Yemen)', + "code" => "ar-ye", + "name" => "Arabic (Yemen)", ], [ - 'code' => 'as', - 'name' => 'Assamese', + "code" => "as", + "name" => "Assamese", ], [ - 'code' => 'az', - 'name' => 'Azerbaijani', + "code" => "az", + "name" => "Azerbaijani", ], [ - 'code' => 'be', - 'name' => 'Belarusian', + "code" => "be", + "name" => "Belarusian", ], [ - 'code' => 'bg', - 'name' => 'Bulgarian', + "code" => "bg", + "name" => "Bulgarian", ], [ - 'code' => 'bh', - 'name' => 'Bihari', + "code" => "bh", + "name" => "Bihari", ], [ - 'code' => 'bn', - 'name' => 'Bengali', + "code" => "bn", + "name" => "Bengali", ], [ - 'code' => 'bs', - 'name' => 'Bosnian', + "code" => "bs", + "name" => "Bosnian", ], [ - 'code' => 'ca', - 'name' => 'Catalan', + "code" => "ca", + "name" => "Catalan", ], [ - 'code' => 'cs', - 'name' => 'Czech', + "code" => "cs", + "name" => "Czech", ], [ - 'code' => 'cy', - 'name' => 'Welsh', + "code" => "cy", + "name" => "Welsh", ], [ - 'code' => 'da', - 'name' => 'Danish', + "code" => "da", + "name" => "Danish", ], [ - 'code' => 'de', - 'name' => 'German (Standard)', + "code" => "de", + "name" => "German (Standard)", ], [ - 'code' => 'de-at', - 'name' => 'German (Austria)', + "code" => "de-at", + "name" => "German (Austria)", ], [ - 'code' => 'de-ch', - 'name' => 'German (Switzerland)', + "code" => "de-ch", + "name" => "German (Switzerland)", ], [ - 'code' => 'de-li', - 'name' => 'German (Liechtenstein)', + "code" => "de-li", + "name" => "German (Liechtenstein)", ], [ - 'code' => 'de-lu', - 'name' => 'German (Luxembourg)', + "code" => "de-lu", + "name" => "German (Luxembourg)", ], [ - 'code' => 'el', - 'name' => 'Greek', + "code" => "el", + "name" => "Greek", ], [ - 'code' => 'en', - 'name' => 'English', + "code" => "en", + "name" => "English", ], [ - 'code' => 'en-au', - 'name' => 'English (Australia)', + "code" => "en-au", + "name" => "English (Australia)", ], [ - 'code' => 'en-bz', - 'name' => 'English (Belize)', + "code" => "en-bz", + "name" => "English (Belize)", ], [ - 'code' => 'en-ca', - 'name' => 'English (Canada)', + "code" => "en-ca", + "name" => "English (Canada)", ], [ - 'code' => 'en-gb', - 'name' => 'English (United Kingdom)', + "code" => "en-gb", + "name" => "English (United Kingdom)", ], [ - 'code' => 'en-ie', - 'name' => 'English (Ireland)', + "code" => "en-ie", + "name" => "English (Ireland)", ], [ - 'code' => 'en-jm', - 'name' => 'English (Jamaica)', + "code" => "en-jm", + "name" => "English (Jamaica)", ], [ - 'code' => 'en-nz', - 'name' => 'English (New Zealand)', + "code" => "en-nz", + "name" => "English (New Zealand)", ], [ - 'code' => 'en-tt', - 'name' => 'English (Trinidad)', + "code" => "en-tt", + "name" => "English (Trinidad)", ], [ - 'code' => 'en-us', - 'name' => 'English (United States)', + "code" => "en-us", + "name" => "English (United States)", ], [ - 'code' => 'en-za', - 'name' => 'English (South Africa)', + "code" => "en-za", + "name" => "English (South Africa)", ], [ - 'code' => 'eo', - 'name' => 'Esperanto', + "code" => "eo", + "name" => "Esperanto", ], [ - 'code' => 'es', - 'name' => 'Spanish (Spain)', + "code" => "es", + "name" => "Spanish (Spain)", ], [ - 'code' => 'es-ar', - 'name' => 'Spanish (Argentina)', + "code" => "es-ar", + "name" => "Spanish (Argentina)", ], [ - 'code' => 'es-bo', - 'name' => 'Spanish (Bolivia)', + "code" => "es-bo", + "name" => "Spanish (Bolivia)", ], [ - 'code' => 'es-cl', - 'name' => 'Spanish (Chile)', + "code" => "es-cl", + "name" => "Spanish (Chile)", ], [ - 'code' => 'es-co', - 'name' => 'Spanish (Colombia)', + "code" => "es-co", + "name" => "Spanish (Colombia)", ], [ - 'code' => 'es-cr', - 'name' => 'Spanish (Costa Rica)', + "code" => "es-cr", + "name" => "Spanish (Costa Rica)", ], [ - 'code' => 'es-do', - 'name' => 'Spanish (Dominican Republic)', + "code" => "es-do", + "name" => "Spanish (Dominican Republic)", ], [ - 'code' => 'es-ec', - 'name' => 'Spanish (Ecuador)', + "code" => "es-ec", + "name" => "Spanish (Ecuador)", ], [ - 'code' => 'es-gt', - 'name' => 'Spanish (Guatemala)', + "code" => "es-gt", + "name" => "Spanish (Guatemala)", ], [ - 'code' => 'es-hn', - 'name' => 'Spanish (Honduras)', + "code" => "es-hn", + "name" => "Spanish (Honduras)", ], [ - 'code' => 'es-mx', - 'name' => 'Spanish (Mexico)', + "code" => "es-mx", + "name" => "Spanish (Mexico)", ], [ - 'code' => 'es-ni', - 'name' => 'Spanish (Nicaragua)', + "code" => "es-ni", + "name" => "Spanish (Nicaragua)", ], [ - 'code' => 'es-pa', - 'name' => 'Spanish (Panama)', + "code" => "es-pa", + "name" => "Spanish (Panama)", ], [ - 'code' => 'es-pe', - 'name' => 'Spanish (Peru)', + "code" => "es-pe", + "name" => "Spanish (Peru)", ], [ - 'code' => 'es-pr', - 'name' => 'Spanish (Puerto Rico)', + "code" => "es-pr", + "name" => "Spanish (Puerto Rico)", ], [ - 'code' => 'es-py', - 'name' => 'Spanish (Paraguay)', + "code" => "es-py", + "name" => "Spanish (Paraguay)", ], [ - 'code' => 'es-sv', - 'name' => 'Spanish (El Salvador)', + "code" => "es-sv", + "name" => "Spanish (El Salvador)", ], [ - 'code' => 'es-uy', - 'name' => 'Spanish (Uruguay)', + "code" => "es-uy", + "name" => "Spanish (Uruguay)", ], [ - 'code' => 'es-ve', - 'name' => 'Spanish (Venezuela)', + "code" => "es-ve", + "name" => "Spanish (Venezuela)", ], [ - 'code' => 'et', - 'name' => 'Estonian', + "code" => "et", + "name" => "Estonian", ], [ - 'code' => 'eu', - 'name' => 'Basque', + "code" => "eu", + "name" => "Basque", ], [ - 'code' => 'fa', - 'name' => 'Farsi', + "code" => "fa", + "name" => "Farsi", ], [ - 'code' => 'fi', - 'name' => 'Finnish', + "code" => "fi", + "name" => "Finnish", ], [ - 'code' => 'fo', - 'name' => 'Faeroese', + "code" => "fo", + "name" => "Faeroese", ], [ - 'code' => 'fr', - 'name' => 'French (Standard)', + "code" => "fr", + "name" => "French (Standard)", ], [ - 'code' => 'fr-be', - 'name' => 'French (Belgium)', + "code" => "fr-be", + "name" => "French (Belgium)", ], [ - 'code' => 'fr-ca', - 'name' => 'French (Canada)', + "code" => "fr-ca", + "name" => "French (Canada)", ], [ - 'code' => 'fr-ch', - 'name' => 'French (Switzerland)', + "code" => "fr-ch", + "name" => "French (Switzerland)", ], [ - 'code' => 'fr-lu', - 'name' => 'French (Luxembourg)', + "code" => "fr-lu", + "name" => "French (Luxembourg)", ], [ - 'code' => 'ga', - 'name' => 'Irish', + "code" => "ga", + "name" => "Irish", ], [ - 'code' => 'gd', - 'name' => 'Gaelic (Scotland)', + "code" => "gd", + "name" => "Gaelic (Scotland)", ], [ - 'code' => 'he', - 'name' => 'Hebrew', + "code" => "he", + "name" => "Hebrew", ], [ - 'code' => 'hi', - 'name' => 'Hindi', + "code" => "hi", + "name" => "Hindi", ], [ - 'code' => 'hr', - 'name' => 'Croatian', + "code" => "hr", + "name" => "Croatian", ], [ - 'code' => 'hu', - 'name' => 'Hungarian', + "code" => "hu", + "name" => "Hungarian", ], [ - 'code' => 'id', - 'name' => 'Indonesian', + "code" => "id", + "name" => "Indonesian", ], [ - 'code' => 'is', - 'name' => 'Icelandic', + "code" => "is", + "name" => "Icelandic", ], [ - 'code' => 'it', - 'name' => 'Italian (Standard)', + "code" => "it", + "name" => "Italian (Standard)", ], [ - 'code' => 'it-ch', - 'name' => 'Italian (Switzerland)', + "code" => "it-ch", + "name" => "Italian (Switzerland)", ], [ - 'code' => 'ja', - 'name' => 'Japanese', + "code" => "ja", + "name" => "Japanese", ], [ - 'code' => 'ji', - 'name' => 'Yiddish', + "code" => "ji", + "name" => "Yiddish", ], [ - 'code' => 'ko', - 'name' => 'Korean', + "code" => "ko", + "name" => "Korean", ], [ - 'code' => 'ku', - 'name' => 'Kurdish', + "code" => "ku", + "name" => "Kurdish", ], [ - 'code' => 'lt', - 'name' => 'Lithuanian', + "code" => "lt", + "name" => "Lithuanian", ], [ - 'code' => 'lv', - 'name' => 'Latvian', + "code" => "lv", + "name" => "Latvian", ], [ - 'code' => 'mk', - 'name' => 'Macedonian (FYROM)', + "code" => "mk", + "name" => "Macedonian (FYROM)", ], [ - 'code' => 'ml', - 'name' => 'Malayalam', + "code" => "ml", + "name" => "Malayalam", ], [ - 'code' => 'ms', - 'name' => 'Malaysian', + "code" => "ms", + "name" => "Malaysian", ], [ - 'code' => 'mt', - 'name' => 'Maltese', + "code" => "mt", + "name" => "Maltese", ], [ - 'code' => 'nb', - 'name' => 'Norwegian (Bokmål)', + "code" => "nb", + "name" => "Norwegian (Bokmål)", ], [ - 'code' => 'ne', - 'name' => 'Nepali', + "code" => "ne", + "name" => "Nepali", ], [ - 'code' => 'nl', - 'name' => 'Dutch (Standard)', + "code" => "nl", + "name" => "Dutch (Standard)", ], [ - 'code' => 'nl-be', - 'name' => 'Dutch (Belgium)', + "code" => "nl-be", + "name" => "Dutch (Belgium)", ], [ - 'code' => 'nn', - 'name' => 'Norwegian (Nynorsk)', + "code" => "nn", + "name" => "Norwegian (Nynorsk)", ], [ - 'code' => 'no', - 'name' => 'Norwegian', + "code" => "no", + "name" => "Norwegian", ], [ - 'code' => 'pa', - 'name' => 'Punjabi', + "code" => "pa", + "name" => "Punjabi", ], [ - 'code' => 'pl', - 'name' => 'Polish', + "code" => "pl", + "name" => "Polish", ], [ - 'code' => 'pt', - 'name' => 'Portuguese (Portugal)', + "code" => "pt", + "name" => "Portuguese (Portugal)", ], [ - 'code' => 'pt-br', - 'name' => 'Portuguese (Brazil)', + "code" => "pt-br", + "name" => "Portuguese (Brazil)", ], [ - 'code' => 'rm', - 'name' => 'Rhaeto-Romanic', + "code" => "rm", + "name" => "Rhaeto-Romanic", ], [ - 'code' => 'ro', - 'name' => 'Romanian', + "code" => "ro", + "name" => "Romanian", ], [ - 'code' => 'ro-md', - 'name' => 'Romanian (Republic of Moldova)', + "code" => "ro-md", + "name" => "Romanian (Republic of Moldova)", ], [ - 'code' => 'ru', - 'name' => 'Russian', + "code" => "ru", + "name" => "Russian", ], [ - 'code' => 'ru-md', - 'name' => 'Russian (Republic of Moldova)', + "code" => "ru-md", + "name" => "Russian (Republic of Moldova)", ], [ - 'code' => 'sb', - 'name' => 'Sorbian', + "code" => "sb", + "name" => "Sorbian", ], [ - 'code' => 'sk', - 'name' => 'Slovak', + "code" => "sk", + "name" => "Slovak", ], [ - 'code' => 'sl', - 'name' => 'Slovenian', + "code" => "sl", + "name" => "Slovenian", ], [ - 'code' => 'sq', - 'name' => 'Albanian', + "code" => "sq", + "name" => "Albanian", ], [ - 'code' => 'sr', - 'name' => 'Serbian', + "code" => "sr", + "name" => "Serbian", ], [ - 'code' => 'sv', - 'name' => 'Swedish', + "code" => "sv", + "name" => "Swedish", ], [ - 'code' => 'sv-fi', - 'name' => 'Swedish (Finland)', + "code" => "sv-fi", + "name" => "Swedish (Finland)", ], [ - 'code' => 'th', - 'name' => 'Thai', + "code" => "th", + "name" => "Thai", ], [ - 'code' => 'tn', - 'name' => 'Tswana', + "code" => "tn", + "name" => "Tswana", ], [ - 'code' => 'tr', - 'name' => 'Turkish', + "code" => "tr", + "name" => "Turkish", ], [ - 'code' => 'ts', - 'name' => 'Tsonga', + "code" => "ts", + "name" => "Tsonga", ], [ - 'code' => 'ua', - 'name' => 'Ukrainian', + "code" => "ua", + "name" => "Ukrainian", ], [ - 'code' => 'ur', - 'name' => 'Urdu', + "code" => "ur", + "name" => "Urdu", ], [ - 'code' => 've', - 'name' => 'Venda', + "code" => "ve", + "name" => "Venda", ], [ - 'code' => 'vi', - 'name' => 'Vietnamese', + "code" => "vi", + "name" => "Vietnamese", ], [ - 'code' => 'xh', - 'name' => 'Xhosa', + "code" => "xh", + "name" => "Xhosa", ], [ - 'code' => 'zh-cn', - 'name' => 'Chinese (PRC)', + "code" => "zh-cn", + "name" => "Chinese (PRC)", ], [ - 'code' => 'zh-hk', - 'name' => 'Chinese (Hong Kong)', + "code" => "zh-hk", + "name" => "Chinese (Hong Kong)", ], [ - 'code' => 'zh-sg', - 'name' => 'Chinese (Singapore)', + "code" => "zh-sg", + "name" => "Chinese (Singapore)", ], [ - 'code' => 'zh-tw', - 'name' => 'Chinese (Taiwan)', + "code" => "zh-tw", + "name" => "Chinese (Taiwan)", ], [ - 'code' => 'zu', - 'name' => 'Zulu', + "code" => "zu", + "name" => "Zulu", ], ]; diff --git a/app/config/locale/languages.php b/app/config/locale/languages.php index 318ec27492..6272bd02a6 100644 --- a/app/config/locale/languages.php +++ b/app/config/locale/languages.php @@ -9,923 +9,923 @@ return [ [ - 'code' => 'aa', - 'name' => 'Afar', - 'nativeName' => 'Afar', + "code" => "aa", + "name" => "Afar", + "nativeName" => "Afar" ], [ - 'code' => 'ab', - 'name' => 'Abkhazian', - 'nativeName' => 'Аҧсуа', + "code" => "ab", + "name" => "Abkhazian", + "nativeName" => "Аҧсуа" ], [ - 'code' => 'af', - 'name' => 'Afrikaans', - 'nativeName' => 'Afrikaans', + "code" => "af", + "name" => "Afrikaans", + "nativeName" => "Afrikaans" ], [ - 'code' => 'ak', - 'name' => 'Akan', - 'nativeName' => 'Akana', + "code" => "ak", + "name" => "Akan", + "nativeName" => "Akana" ], [ - 'code' => 'am', - 'name' => 'Amharic', - 'nativeName' => 'አማርኛ', + "code" => "am", + "name" => "Amharic", + "nativeName" => "አማርኛ" ], [ - 'code' => 'an', - 'name' => 'Aragonese', - 'nativeName' => 'Aragonés', + "code" => "an", + "name" => "Aragonese", + "nativeName" => "Aragonés" ], [ - 'code' => 'ar', - 'name' => 'Arabic', - 'nativeName' => 'العربية', + "code" => "ar", + "name" => "Arabic", + "nativeName" => "العربية" ], [ - 'code' => 'as', - 'name' => 'Assamese', - 'nativeName' => 'অসমীয়া', + "code" => "as", + "name" => "Assamese", + "nativeName" => "অসমীয়া" ], [ - 'code' => 'av', - 'name' => 'Avar', - 'nativeName' => 'Авар', + "code" => "av", + "name" => "Avar", + "nativeName" => "Авар" ], [ - 'code' => 'ay', - 'name' => 'Aymara', - 'nativeName' => 'Aymar', + "code" => "ay", + "name" => "Aymara", + "nativeName" => "Aymar" ], [ - 'code' => 'az', - 'name' => 'Azerbaijani', - 'nativeName' => 'Azərbaycanca / آذربايجان', + "code" => "az", + "name" => "Azerbaijani", + "nativeName" => "Azərbaycanca / آذربايجان" ], [ - 'code' => 'ba', - 'name' => 'Bashkir', - 'nativeName' => 'Башҡорт', + "code" => "ba", + "name" => "Bashkir", + "nativeName" => "Башҡорт" ], [ - 'code' => 'be', - 'name' => 'Belarusian', - 'nativeName' => 'Беларуская', + "code" => "be", + "name" => "Belarusian", + "nativeName" => "Беларуская" ], [ - 'code' => 'bg', - 'name' => 'Bulgarian', - 'nativeName' => 'Български', + "code" => "bg", + "name" => "Bulgarian", + "nativeName" => "Български" ], [ - 'code' => 'bh', - 'name' => 'Bihari', - 'nativeName' => 'भोजपुरी', + "code" => "bh", + "name" => "Bihari", + "nativeName" => "भोजपुरी" ], [ - 'code' => 'bi', - 'name' => 'Bislama', - 'nativeName' => 'Bislama', + "code" => "bi", + "name" => "Bislama", + "nativeName" => "Bislama" ], [ - 'code' => 'bm', - 'name' => 'Bambara', - 'nativeName' => 'Bamanankan', + "code" => "bm", + "name" => "Bambara", + "nativeName" => "Bamanankan" ], [ - 'code' => 'bn', - 'name' => 'Bengali', - 'nativeName' => 'বাংলা', + "code" => "bn", + "name" => "Bengali", + "nativeName" => "বাংলা" ], [ - 'code' => 'bo', - 'name' => 'Tibetan', - 'nativeName' => 'བོད་ཡིག / Bod skad', + "code" => "bo", + "name" => "Tibetan", + "nativeName" => "བོད་ཡིག / Bod skad" ], [ - 'code' => 'br', - 'name' => 'Breton', - 'nativeName' => 'Brezhoneg', + "code" => "br", + "name" => "Breton", + "nativeName" => "Brezhoneg" ], [ - 'code' => 'bs', - 'name' => 'Bosnian', - 'nativeName' => 'Bosanski', + "code" => "bs", + "name" => "Bosnian", + "nativeName" => "Bosanski" ], [ - 'code' => 'ca', - 'name' => 'Catalan', - 'nativeName' => 'Català', + "code" => "ca", + "name" => "Catalan", + "nativeName" => "Català" ], [ - 'code' => 'ce', - 'name' => 'Chechen', - 'nativeName' => 'Нохчийн', + "code" => "ce", + "name" => "Chechen", + "nativeName" => "Нохчийн" ], [ - 'code' => 'ch', - 'name' => 'Chamorro', - 'nativeName' => 'Chamoru', + "code" => "ch", + "name" => "Chamorro", + "nativeName" => "Chamoru" ], [ - 'code' => 'co', - 'name' => 'Corsican', - 'nativeName' => 'Corsu', + "code" => "co", + "name" => "Corsican", + "nativeName" => "Corsu" ], [ - 'code' => 'cr', - 'name' => 'Cree', - 'nativeName' => 'Nehiyaw', + "code" => "cr", + "name" => "Cree", + "nativeName" => "Nehiyaw" ], [ - 'code' => 'cs', - 'name' => 'Czech', - 'nativeName' => 'Česky', + "code" => "cs", + "name" => "Czech", + "nativeName" => "Česky" ], [ - 'code' => 'cu', - 'name' => 'Old Church Slavonic / Old Bulgarian', - 'nativeName' => 'словѣньскъ / slověnĭskŭ', + "code" => "cu", + "name" => "Old Church Slavonic / Old Bulgarian", + "nativeName" => "словѣньскъ / slověnĭskŭ" ], [ - 'code' => 'cv', - 'name' => 'Chuvash', - 'nativeName' => 'Чăваш', + "code" => "cv", + "name" => "Chuvash", + "nativeName" => "Чăваш" ], [ - 'code' => 'cy', - 'name' => 'Welsh', - 'nativeName' => 'Cymraeg', + "code" => "cy", + "name" => "Welsh", + "nativeName" => "Cymraeg" ], [ - 'code' => 'da', - 'name' => 'Danish', - 'nativeName' => 'Dansk', + "code" => "da", + "name" => "Danish", + "nativeName" => "Dansk" ], [ - 'code' => 'de', - 'name' => 'German', - 'nativeName' => 'Deutsch', + "code" => "de", + "name" => "German", + "nativeName" => "Deutsch" ], [ - 'code' => 'dv', - 'name' => 'Divehi', - 'nativeName' => 'ދިވެހިބަސް', + "code" => "dv", + "name" => "Divehi", + "nativeName" => "ދިވެހިބަސް" ], [ - 'code' => 'dz', - 'name' => 'Dzongkha', - 'nativeName' => 'ཇོང་ཁ', + "code" => "dz", + "name" => "Dzongkha", + "nativeName" => "ཇོང་ཁ" ], [ - 'code' => 'ee', - 'name' => 'Ewe', - 'nativeName' => 'Ɛʋɛ', + "code" => "ee", + "name" => "Ewe", + "nativeName" => "Ɛʋɛ" ], [ - 'code' => 'el', - 'name' => 'Greek', - 'nativeName' => 'Ελληνικά', + "code" => "el", + "name" => "Greek", + "nativeName" => "Ελληνικά" ], [ - 'code' => 'en', - 'name' => 'English', - 'nativeName' => 'English', + "code" => "en", + "name" => "English", + "nativeName" => "English" ], [ - 'code' => 'eo', - 'name' => 'Esperanto', - 'nativeName' => 'Esperanto', + "code" => "eo", + "name" => "Esperanto", + "nativeName" => "Esperanto" ], [ - 'code' => 'es', - 'name' => 'Spanish', - 'nativeName' => 'Español', + "code" => "es", + "name" => "Spanish", + "nativeName" => "Español" ], [ - 'code' => 'et', - 'name' => 'Estonian', - 'nativeName' => 'Eesti', + "code" => "et", + "name" => "Estonian", + "nativeName" => "Eesti" ], [ - 'code' => 'eu', - 'name' => 'Basque', - 'nativeName' => 'Euskara', + "code" => "eu", + "name" => "Basque", + "nativeName" => "Euskara" ], [ - 'code' => 'fa', - 'name' => 'Persian', - 'nativeName' => 'فارسی', + "code" => "fa", + "name" => "Persian", + "nativeName" => "فارسی" ], [ - 'code' => 'ff', - 'name' => 'Peul', - 'nativeName' => 'Fulfulde', + "code" => "ff", + "name" => "Peul", + "nativeName" => "Fulfulde" ], [ - 'code' => 'fi', - 'name' => 'Finnish', - 'nativeName' => 'Suomi', + "code" => "fi", + "name" => "Finnish", + "nativeName" => "Suomi" ], [ - 'code' => 'fj', - 'name' => 'Fijian', - 'nativeName' => 'Na Vosa Vakaviti', + "code" => "fj", + "name" => "Fijian", + "nativeName" => "Na Vosa Vakaviti" ], [ - 'code' => 'fo', - 'name' => 'Faroese', - 'nativeName' => 'Føroyskt', + "code" => "fo", + "name" => "Faroese", + "nativeName" => "Føroyskt" ], [ - 'code' => 'fr', - 'name' => 'French', - 'nativeName' => 'Français', + "code" => "fr", + "name" => "French", + "nativeName" => "Français" ], [ - 'code' => 'fy', - 'name' => 'West Frisian', - 'nativeName' => 'Frysk', + "code" => "fy", + "name" => "West Frisian", + "nativeName" => "Frysk" ], [ - 'code' => 'ga', - 'name' => 'Irish', - 'nativeName' => 'Gaeilge', + "code" => "ga", + "name" => "Irish", + "nativeName" => "Gaeilge" ], [ - 'code' => 'gd', - 'name' => 'Scottish Gaelic', - 'nativeName' => 'Gàidhlig', + "code" => "gd", + "name" => "Scottish Gaelic", + "nativeName" => "Gàidhlig" ], [ - 'code' => 'gl', - 'name' => 'Galician', - 'nativeName' => 'Galego', + "code" => "gl", + "name" => "Galician", + "nativeName" => "Galego" ], [ - 'code' => 'gn', - 'name' => 'Guarani', - 'nativeName' => "Avañe'ẽ", + "code" => "gn", + "name" => "Guarani", + "nativeName" => "Avañe'ẽ" ], [ - 'code' => 'gu', - 'name' => 'Gujarati', - 'nativeName' => 'ગુજરાતી', + "code" => "gu", + "name" => "Gujarati", + "nativeName" => "ગુજરાતી" ], [ - 'code' => 'gv', - 'name' => 'Manx', - 'nativeName' => 'Gaelg', + "code" => "gv", + "name" => "Manx", + "nativeName" => "Gaelg" ], [ - 'code' => 'ha', - 'name' => 'Hausa', - 'nativeName' => 'هَوُسَ', + "code" => "ha", + "name" => "Hausa", + "nativeName" => "هَوُسَ" ], [ - 'code' => 'he', - 'name' => 'Hebrew', - 'nativeName' => 'עברית', + "code" => "he", + "name" => "Hebrew", + "nativeName" => "עברית" ], [ - 'code' => 'hi', - 'name' => 'Hindi', - 'nativeName' => 'हिन्दी / हिंदी ', + "code" => "hi", + "name" => "Hindi", + "nativeName" => "हिन्दी / हिंदी " ], [ - 'code' => 'ho', - 'name' => 'Hiri Motu', - 'nativeName' => 'Hiri Motu', + "code" => "ho", + "name" => "Hiri Motu", + "nativeName" => "Hiri Motu" ], [ - 'code' => 'hr', - 'name' => 'Croatian', - 'nativeName' => 'Hrvatski', + "code" => "hr", + "name" => "Croatian", + "nativeName" => "Hrvatski" ], [ - 'code' => 'ht', - 'name' => 'Haitian', - 'nativeName' => 'Krèyol ayisyen', + "code" => "ht", + "name" => "Haitian", + "nativeName" => "Krèyol ayisyen" ], [ - 'code' => 'hu', - 'name' => 'Hungarian', - 'nativeName' => 'Magyar', + "code" => "hu", + "name" => "Hungarian", + "nativeName" => "Magyar" ], [ - 'code' => 'hy', - 'name' => 'Armenian', - 'nativeName' => 'Հայերեն', + "code" => "hy", + "name" => "Armenian", + "nativeName" => "Հայերեն" ], [ - 'code' => 'hz', - 'name' => 'Herero', - 'nativeName' => 'Otsiherero', + "code" => "hz", + "name" => "Herero", + "nativeName" => "Otsiherero" ], [ - 'code' => 'ia', - 'name' => 'Interlingua', - 'nativeName' => 'Interlingua', + "code" => "ia", + "name" => "Interlingua", + "nativeName" => "Interlingua" ], [ - 'code' => 'id', - 'name' => 'Indonesian', - 'nativeName' => 'Bahasa Indonesia', + "code" => "id", + "name" => "Indonesian", + "nativeName" => "Bahasa Indonesia" ], [ - 'code' => 'ie', - 'name' => 'Interlingue', - 'nativeName' => 'Interlingue', + "code" => "ie", + "name" => "Interlingue", + "nativeName" => "Interlingue" ], [ - 'code' => 'ig', - 'name' => 'Igbo', - 'nativeName' => 'Igbo', + "code" => "ig", + "name" => "Igbo", + "nativeName" => "Igbo" ], [ - 'code' => 'ii', - 'name' => 'Sichuan Yi', - 'nativeName' => 'ꆇꉙ / 四川彝语', + "code" => "ii", + "name" => "Sichuan Yi", + "nativeName" => "ꆇꉙ / 四川彝语" ], [ - 'code' => 'ik', - 'name' => 'Inupiak', - 'nativeName' => 'Iñupiak', + "code" => "ik", + "name" => "Inupiak", + "nativeName" => "Iñupiak" ], [ - 'code' => 'io', - 'name' => 'Ido', - 'nativeName' => 'Ido', + "code" => "io", + "name" => "Ido", + "nativeName" => "Ido" ], [ - 'code' => 'is', - 'name' => 'Icelandic', - 'nativeName' => 'Íslenska', + "code" => "is", + "name" => "Icelandic", + "nativeName" => "Íslenska" ], [ - 'code' => 'it', - 'name' => 'Italian', - 'nativeName' => 'Italiano', + "code" => "it", + "name" => "Italian", + "nativeName" => "Italiano" ], [ - 'code' => 'iu', - 'name' => 'Inuktitut', - 'nativeName' => 'ᐃᓄᒃᑎᑐᑦ', + "code" => "iu", + "name" => "Inuktitut", + "nativeName" => "ᐃᓄᒃᑎᑐᑦ" ], [ - 'code' => 'ja', - 'name' => 'Japanese', - 'nativeName' => '日本語', + "code" => "ja", + "name" => "Japanese", + "nativeName" => "日本語" ], [ - 'code' => 'jv', - 'name' => 'Javanese', - 'nativeName' => 'Basa Jawa', + "code" => "jv", + "name" => "Javanese", + "nativeName" => "Basa Jawa" ], [ - 'code' => 'ka', - 'name' => 'Georgian', - 'nativeName' => 'ქართული', + "code" => "ka", + "name" => "Georgian", + "nativeName" => "ქართული" ], [ - 'code' => 'kg', - 'name' => 'Kongo', - 'nativeName' => 'KiKongo', + "code" => "kg", + "name" => "Kongo", + "nativeName" => "KiKongo" ], [ - 'code' => 'ki', - 'name' => 'Kikuyu', - 'nativeName' => 'Gĩkũyũ', + "code" => "ki", + "name" => "Kikuyu", + "nativeName" => "Gĩkũyũ" ], [ - 'code' => 'kj', - 'name' => 'Kuanyama', - 'nativeName' => 'Kuanyama', + "code" => "kj", + "name" => "Kuanyama", + "nativeName" => "Kuanyama" ], [ - 'code' => 'kk', - 'name' => 'Kazakh', - 'nativeName' => 'Қазақша', + "code" => "kk", + "name" => "Kazakh", + "nativeName" => "Қазақша" ], [ - 'code' => 'kl', - 'name' => 'Greenlandic', - 'nativeName' => 'Kalaallisut', + "code" => "kl", + "name" => "Greenlandic", + "nativeName" => "Kalaallisut" ], [ - 'code' => 'km', - 'name' => 'Khmer', - 'nativeName' => 'ភាសាខ្មែរ', + "code" => "km", + "name" => "Khmer", + "nativeName" => "ភាសាខ្មែរ" ], [ - 'code' => 'kn', - 'name' => 'Kannada', - 'nativeName' => 'ಕನ್ನಡ', + "code" => "kn", + "name" => "Kannada", + "nativeName" => "ಕನ್ನಡ" ], [ - 'code' => 'ko', - 'name' => 'Korean', - 'nativeName' => '한국어', + "code" => "ko", + "name" => "Korean", + "nativeName" => "한국어" ], [ - 'code' => 'kr', - 'name' => 'Kanuri', - 'nativeName' => 'Kanuri', + "code" => "kr", + "name" => "Kanuri", + "nativeName" => "Kanuri" ], [ - 'code' => 'ks', - 'name' => 'Kashmiri', - 'nativeName' => 'कश्मीरी / كشميري', + "code" => "ks", + "name" => "Kashmiri", + "nativeName" => "कश्मीरी / كشميري" ], [ - 'code' => 'ku', - 'name' => 'Kurdish', - 'nativeName' => 'Kurdî / كوردی', + "code" => "ku", + "name" => "Kurdish", + "nativeName" => "Kurdî / كوردی" ], [ - 'code' => 'kv', - 'name' => 'Komi', - 'nativeName' => 'Коми', + "code" => "kv", + "name" => "Komi", + "nativeName" => "Коми" ], [ - 'code' => 'kw', - 'name' => 'Cornish', - 'nativeName' => 'Kernewek', + "code" => "kw", + "name" => "Cornish", + "nativeName" => "Kernewek" ], [ - 'code' => 'ky', - 'name' => 'Kirghiz', - 'nativeName' => 'Kırgızca / Кыргызча', + "code" => "ky", + "name" => "Kirghiz", + "nativeName" => "Kırgızca / Кыргызча" ], [ - 'code' => 'la', - 'name' => 'Latin', - 'nativeName' => 'Latina', + "code" => "la", + "name" => "Latin", + "nativeName" => "Latina" ], [ - 'code' => 'lb', - 'name' => 'Luxembourgish', - 'nativeName' => 'Lëtzebuergesch', + "code" => "lb", + "name" => "Luxembourgish", + "nativeName" => "Lëtzebuergesch" ], [ - 'code' => 'lg', - 'name' => 'Ganda', - 'nativeName' => 'Luganda', + "code" => "lg", + "name" => "Ganda", + "nativeName" => "Luganda" ], [ - 'code' => 'li', - 'name' => 'Limburgian', - 'nativeName' => 'Limburgs', + "code" => "li", + "name" => "Limburgian", + "nativeName" => "Limburgs" ], [ - 'code' => 'ln', - 'name' => 'Lingala', - 'nativeName' => 'Lingála', + "code" => "ln", + "name" => "Lingala", + "nativeName" => "Lingála" ], [ - 'code' => 'lo', - 'name' => 'Laotian', - 'nativeName' => 'ລາວ / Pha xa lao', + "code" => "lo", + "name" => "Laotian", + "nativeName" => "ລາວ / Pha xa lao" ], [ - 'code' => 'lt', - 'name' => 'Lithuanian', - 'nativeName' => 'Lietuvių', + "code" => "lt", + "name" => "Lithuanian", + "nativeName" => "Lietuvių" ], [ - 'code' => 'lu', - 'name' => 'Luba-Katanga', - 'nativeName' => 'Tshiluba', + "code" => "lu", + "name" => "Luba-Katanga", + "nativeName" => "Tshiluba" ], [ - 'code' => 'lv', - 'name' => 'Latvian', - 'nativeName' => 'Latviešu', + "code" => "lv", + "name" => "Latvian", + "nativeName" => "Latviešu" ], [ - 'code' => 'mg', - 'name' => 'Malagasy', - 'nativeName' => 'Malagasy', + "code" => "mg", + "name" => "Malagasy", + "nativeName" => "Malagasy" ], [ - 'code' => 'mh', - 'name' => 'Marshallese', - 'nativeName' => 'Kajin Majel / Ebon', + "code" => "mh", + "name" => "Marshallese", + "nativeName" => "Kajin Majel / Ebon" ], [ - 'code' => 'mi', - 'name' => 'Maori', - 'nativeName' => 'Māori', + "code" => "mi", + "name" => "Maori", + "nativeName" => "Māori" ], [ - 'code' => 'mk', - 'name' => 'Macedonian', - 'nativeName' => 'Македонски', + "code" => "mk", + "name" => "Macedonian", + "nativeName" => "Македонски" ], [ - 'code' => 'ml', - 'name' => 'Malayalam', - 'nativeName' => 'മലയാളം', + "code" => "ml", + "name" => "Malayalam", + "nativeName" => "മലയാളം" ], [ - 'code' => 'mn', - 'name' => 'Mongolian', - 'nativeName' => 'Монгол', + "code" => "mn", + "name" => "Mongolian", + "nativeName" => "Монгол" ], [ - 'code' => 'mo', - 'name' => 'Moldovan', - 'nativeName' => 'Moldovenească', + "code" => "mo", + "name" => "Moldovan", + "nativeName" => "Moldovenească" ], [ - 'code' => 'mr', - 'name' => 'Marathi', - 'nativeName' => 'मराठी', + "code" => "mr", + "name" => "Marathi", + "nativeName" => "मराठी" ], [ - 'code' => 'ms', - 'name' => 'Malay', - 'nativeName' => 'Bahasa Melayu', + "code" => "ms", + "name" => "Malay", + "nativeName" => "Bahasa Melayu" ], [ - 'code' => 'mt', - 'name' => 'Maltese', - 'nativeName' => 'bil-Malti', + "code" => "mt", + "name" => "Maltese", + "nativeName" => "bil-Malti" ], [ - 'code' => 'my', - 'name' => 'Burmese', - 'nativeName' => 'မြန်မာစာ', + "code" => "my", + "name" => "Burmese", + "nativeName" => "မြန်မာစာ" ], [ - 'code' => 'na', - 'name' => 'Nauruan', - 'nativeName' => 'Dorerin Naoero', + "code" => "na", + "name" => "Nauruan", + "nativeName" => "Dorerin Naoero" ], [ - 'code' => 'nb', - 'name' => 'Norwegian Bokmål', - 'nativeName' => 'Norsk bokmål', + "code" => "nb", + "name" => "Norwegian Bokmål", + "nativeName" => "Norsk bokmål" ], [ - 'code' => 'nd', - 'name' => 'North Ndebele', - 'nativeName' => 'Sindebele', + "code" => "nd", + "name" => "North Ndebele", + "nativeName" => "Sindebele" ], [ - 'code' => 'ne', - 'name' => 'Nepali', - 'nativeName' => 'नेपाली', + "code" => "ne", + "name" => "Nepali", + "nativeName" => "नेपाली" ], [ - 'code' => 'ng', - 'name' => 'Ndonga', - 'nativeName' => 'Oshiwambo', + "code" => "ng", + "name" => "Ndonga", + "nativeName" => "Oshiwambo" ], [ - 'code' => 'nl', - 'name' => 'Dutch', - 'nativeName' => 'Nederlands', + "code" => "nl", + "name" => "Dutch", + "nativeName" => "Nederlands" ], [ - 'code' => 'nn', - 'name' => 'Norwegian Nynorsk', - 'nativeName' => 'Norsk nynorsk', + "code" => "nn", + "name" => "Norwegian Nynorsk", + "nativeName" => "Norsk nynorsk" ], [ - 'code' => 'nr', - 'name' => 'South Ndebele', - 'nativeName' => 'isiNdebele', + "code" => "nr", + "name" => "South Ndebele", + "nativeName" => "isiNdebele" ], [ - 'code' => 'nv', - 'name' => 'Navajo', - 'nativeName' => 'Diné bizaad', + "code" => "nv", + "name" => "Navajo", + "nativeName" => "Diné bizaad" ], [ - 'code' => 'ny', - 'name' => 'Chichewa', - 'nativeName' => 'Chi-Chewa', + "code" => "ny", + "name" => "Chichewa", + "nativeName" => "Chi-Chewa" ], [ - 'code' => 'oc', - 'name' => 'Occitan', - 'nativeName' => 'Occitan', + "code" => "oc", + "name" => "Occitan", + "nativeName" => "Occitan" ], [ - 'code' => 'oj', - 'name' => 'Ojibwa', - 'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin', + "code" => "oj", + "name" => "Ojibwa", + "nativeName" => "ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin" ], [ - 'code' => 'om', - 'name' => 'Oromo', - 'nativeName' => 'Oromoo', + "code" => "om", + "name" => "Oromo", + "nativeName" => "Oromoo" ], [ - 'code' => 'or', - 'name' => 'Oriya', - 'nativeName' => 'ଓଡ଼ିଆ', + "code" => "or", + "name" => "Oriya", + "nativeName" => "ଓଡ଼ିଆ" ], [ - 'code' => 'os', - 'name' => 'Ossetian / Ossetic', - 'nativeName' => 'Иронау', + "code" => "os", + "name" => "Ossetian / Ossetic", + "nativeName" => "Иронау" ], [ - 'code' => 'pa', - 'name' => 'Panjabi / Punjabi', - 'nativeName' => 'ਪੰਜਾਬੀ / पंजाबी / پنجابي', + "code" => "pa", + "name" => "Panjabi / Punjabi", + "nativeName" => "ਪੰਜਾਬੀ / पंजाबी / پنجابي" ], [ - 'code' => 'pi', - 'name' => 'Pali', - 'nativeName' => 'Pāli / पाऴि', + "code" => "pi", + "name" => "Pali", + "nativeName" => "Pāli / पाऴि" ], [ - 'code' => 'pl', - 'name' => 'Polish', - 'nativeName' => 'Polski', + "code" => "pl", + "name" => "Polish", + "nativeName" => "Polski" ], [ - 'code' => 'ps', - 'name' => 'Pashto', - 'nativeName' => 'پښتو', + "code" => "ps", + "name" => "Pashto", + "nativeName" => "پښتو" ], [ - 'code' => 'pt', - 'name' => 'Portuguese', - 'nativeName' => 'Português', + "code" => "pt", + "name" => "Portuguese", + "nativeName" => "Português" ], [ - 'code' => 'qu', - 'name' => 'Quechua', - 'nativeName' => 'Runa Simi', + "code" => "qu", + "name" => "Quechua", + "nativeName" => "Runa Simi" ], [ - 'code' => 'rm', - 'name' => 'Raeto Romance', - 'nativeName' => 'Rumantsch', + "code" => "rm", + "name" => "Raeto Romance", + "nativeName" => "Rumantsch" ], [ - 'code' => 'rn', - 'name' => 'Kirundi', - 'nativeName' => 'Kirundi', + "code" => "rn", + "name" => "Kirundi", + "nativeName" => "Kirundi" ], [ - 'code' => 'ro', - 'name' => 'Romanian', - 'nativeName' => 'Română', + "code" => "ro", + "name" => "Romanian", + "nativeName" => "Română" ], [ - 'code' => 'ru', - 'name' => 'Russian', - 'nativeName' => 'Русский', + "code" => "ru", + "name" => "Russian", + "nativeName" => "Русский" ], [ - 'code' => 'rw', - 'name' => 'Rwandi', - 'nativeName' => 'Kinyarwandi', + "code" => "rw", + "name" => "Rwandi", + "nativeName" => "Kinyarwandi" ], [ - 'code' => 'sa', - 'name' => 'Sanskrit', - 'nativeName' => 'संस्कृतम्', + "code" => "sa", + "name" => "Sanskrit", + "nativeName" => "संस्कृतम्" ], [ - 'code' => 'sc', - 'name' => 'Sardinian', - 'nativeName' => 'Sardu', + "code" => "sc", + "name" => "Sardinian", + "nativeName" => "Sardu" ], [ - 'code' => 'sd', - 'name' => 'Sindhi', - 'nativeName' => 'सिन्धी / सिंधी ', + "code" => "sd", + "name" => "Sindhi", + "nativeName" => "सिन्धी / सिंधी " ], [ - 'code' => 'se', - 'name' => 'Northern Sami', - 'nativeName' => 'Sámegiella', + "code" => "se", + "name" => "Northern Sami", + "nativeName" => "Sámegiella" ], [ - 'code' => 'sg', - 'name' => 'Sango', - 'nativeName' => 'Sängö', + "code" => "sg", + "name" => "Sango", + "nativeName" => "Sängö" ], [ - 'code' => 'sh', - 'name' => 'Serbo-Croatian', - 'nativeName' => 'Srpskohrvatski / Српскохрватски', + "code" => "sh", + "name" => "Serbo-Croatian", + "nativeName" => "Srpskohrvatski / Српскохрватски" ], [ - 'code' => 'si', - 'name' => 'Sinhalese', - 'nativeName' => 'සිංහල', + "code" => "si", + "name" => "Sinhalese", + "nativeName" => "සිංහල" ], [ - 'code' => 'sk', - 'name' => 'Slovak', - 'nativeName' => 'Slovenčina', + "code" => "sk", + "name" => "Slovak", + "nativeName" => "Slovenčina" ], [ - 'code' => 'sl', - 'name' => 'Slovenian', - 'nativeName' => 'Slovenščina', + "code" => "sl", + "name" => "Slovenian", + "nativeName" => "Slovenščina" ], [ - 'code' => 'sm', - 'name' => 'Samoan', - 'nativeName' => 'Gagana Samoa', + "code" => "sm", + "name" => "Samoan", + "nativeName" => "Gagana Samoa" ], [ - 'code' => 'sn', - 'name' => 'Shona', - 'nativeName' => 'chiShona', + "code" => "sn", + "name" => "Shona", + "nativeName" => "chiShona" ], [ - 'code' => 'so', - 'name' => 'Somalia', - 'nativeName' => 'Soomaaliga', + "code" => "so", + "name" => "Somalia", + "nativeName" => "Soomaaliga" ], [ - 'code' => 'sq', - 'name' => 'Albanian', - 'nativeName' => 'Shqip', + "code" => "sq", + "name" => "Albanian", + "nativeName" => "Shqip" ], [ - 'code' => 'sr', - 'name' => 'Serbian', - 'nativeName' => 'Српски', + "code" => "sr", + "name" => "Serbian", + "nativeName" => "Српски" ], [ - 'code' => 'ss', - 'name' => 'Swati', - 'nativeName' => 'SiSwati', + "code" => "ss", + "name" => "Swati", + "nativeName" => "SiSwati" ], [ - 'code' => 'st', - 'name' => 'Southern Sotho', - 'nativeName' => 'Sesotho', + "code" => "st", + "name" => "Southern Sotho", + "nativeName" => "Sesotho" ], [ - 'code' => 'su', - 'name' => 'Sundanese', - 'nativeName' => 'Basa Sunda', + "code" => "su", + "name" => "Sundanese", + "nativeName" => "Basa Sunda" ], [ - 'code' => 'sv', - 'name' => 'Swedish', - 'nativeName' => 'Svenska', + "code" => "sv", + "name" => "Swedish", + "nativeName" => "Svenska" ], [ - 'code' => 'sw', - 'name' => 'Swahili', - 'nativeName' => 'Kiswahili', + "code" => "sw", + "name" => "Swahili", + "nativeName" => "Kiswahili" ], [ - 'code' => 'ta', - 'name' => 'Tamil', - 'nativeName' => 'தமிழ்', + "code" => "ta", + "name" => "Tamil", + "nativeName" => "தமிழ்" ], [ - 'code' => 'te', - 'name' => 'Telugu', - 'nativeName' => 'తెలుగు', + "code" => "te", + "name" => "Telugu", + "nativeName" => "తెలుగు" ], [ - 'code' => 'tg', - 'name' => 'Tajik', - 'nativeName' => 'Тоҷикӣ', + "code" => "tg", + "name" => "Tajik", + "nativeName" => "Тоҷикӣ" ], [ - 'code' => 'th', - 'name' => 'Thai', - 'nativeName' => 'ไทย / Phasa Thai', + "code" => "th", + "name" => "Thai", + "nativeName" => "ไทย / Phasa Thai" ], [ - 'code' => 'ti', - 'name' => 'Tigrinya', - 'nativeName' => 'ትግርኛ', + "code" => "ti", + "name" => "Tigrinya", + "nativeName" => "ትግርኛ" ], [ - 'code' => 'tk', - 'name' => 'Turkmen', - 'nativeName' => 'Туркмен / تركمن', + "code" => "tk", + "name" => "Turkmen", + "nativeName" => "Туркмен / تركمن" ], [ - 'code' => 'tl', - 'name' => 'Tagalog / Filipino', - 'nativeName' => 'Tagalog', + "code" => "tl", + "name" => "Tagalog / Filipino", + "nativeName" => "Tagalog" ], [ - 'code' => 'tn', - 'name' => 'Tswana', - 'nativeName' => 'Setswana', + "code" => "tn", + "name" => "Tswana", + "nativeName" => "Setswana" ], [ - 'code' => 'to', - 'name' => 'Tonga', - 'nativeName' => 'Lea Faka-Tonga', + "code" => "to", + "name" => "Tonga", + "nativeName" => "Lea Faka-Tonga" ], [ - 'code' => 'tr', - 'name' => 'Turkish', - 'nativeName' => 'Türkçe', + "code" => "tr", + "name" => "Turkish", + "nativeName" => "Türkçe" ], [ - 'code' => 'ts', - 'name' => 'Tsonga', - 'nativeName' => 'Xitsonga', + "code" => "ts", + "name" => "Tsonga", + "nativeName" => "Xitsonga" ], [ - 'code' => 'tt', - 'name' => 'Tatar', - 'nativeName' => 'Tatarça', + "code" => "tt", + "name" => "Tatar", + "nativeName" => "Tatarça" ], [ - 'code' => 'tw', - 'name' => 'Twi', - 'nativeName' => 'Twi', + "code" => "tw", + "name" => "Twi", + "nativeName" => "Twi" ], [ - 'code' => 'ty', - 'name' => 'Tahitian', - 'nativeName' => 'Reo Mā`ohi', + "code" => "ty", + "name" => "Tahitian", + "nativeName" => "Reo Mā`ohi" ], [ - 'code' => 'ug', - 'name' => 'Uyghur', - 'nativeName' => 'Uyƣurqə / ئۇيغۇرچە', + "code" => "ug", + "name" => "Uyghur", + "nativeName" => "Uyƣurqə / ئۇيغۇرچە" ], [ - 'code' => 'uk', - 'name' => 'Ukrainian', - 'nativeName' => 'Українська', + "code" => "uk", + "name" => "Ukrainian", + "nativeName" => "Українська" ], [ - 'code' => 'ur', - 'name' => 'Urdu', - 'nativeName' => 'اردو', + "code" => "ur", + "name" => "Urdu", + "nativeName" => "اردو" ], [ - 'code' => 'uz', - 'name' => 'Uzbek', - 'nativeName' => 'Ўзбек', + "code" => "uz", + "name" => "Uzbek", + "nativeName" => "Ўзбек" ], [ - 'code' => 've', - 'name' => 'Venda', - 'nativeName' => 'Tshivenḓa', + "code" => "ve", + "name" => "Venda", + "nativeName" => "Tshivenḓa" ], [ - 'code' => 'vi', - 'name' => 'Vietnamese', - 'nativeName' => 'Tiếng Việt', + "code" => "vi", + "name" => "Vietnamese", + "nativeName" => "Tiếng Việt" ], [ - 'code' => 'vo', - 'name' => 'Volapük', - 'nativeName' => 'Volapük', + "code" => "vo", + "name" => "Volapük", + "nativeName" => "Volapük" ], [ - 'code' => 'wa', - 'name' => 'Walloon', - 'nativeName' => 'Walon', + "code" => "wa", + "name" => "Walloon", + "nativeName" => "Walon" ], [ - 'code' => 'wo', - 'name' => 'Wolof', - 'nativeName' => 'Wollof', + "code" => "wo", + "name" => "Wolof", + "nativeName" => "Wollof" ], [ - 'code' => 'xh', - 'name' => 'Xhosa', - 'nativeName' => 'isiXhosa', + "code" => "xh", + "name" => "Xhosa", + "nativeName" => "isiXhosa" ], [ - 'code' => 'yi', - 'name' => 'Yiddish', - 'nativeName' => 'ייִדיש', + "code" => "yi", + "name" => "Yiddish", + "nativeName" => "ייִדיש" ], [ - 'code' => 'yo', - 'name' => 'Yoruba', - 'nativeName' => 'Yorùbá', + "code" => "yo", + "name" => "Yoruba", + "nativeName" => "Yorùbá" ], [ - 'code' => 'za', - 'name' => 'Zhuang', - 'nativeName' => 'Cuengh / Tôô / 壮语', + "code" => "za", + "name" => "Zhuang", + "nativeName" => "Cuengh / Tôô / 壮语" ], [ - 'code' => 'zh', - 'name' => 'Chinese', - 'nativeName' => '中文', + "code" => "zh", + "name" => "Chinese", + "nativeName" => "中文" ], [ - 'code' => 'zu', - 'name' => 'Zulu', - 'nativeName' => 'isiZulu', - ], + "code" => "zu", + "name" => "Zulu", + "nativeName" => "isiZulu" + ] ]; diff --git a/app/config/locale/templates.php b/app/config/locale/templates.php index 9c365813a7..f2672c04a0 100644 --- a/app/config/locale/templates.php +++ b/app/config/locale/templates.php @@ -10,6 +10,6 @@ return [ 'sms' => [ 'verification', 'login', - 'invitation', - ], + 'invitation' + ] ]; diff --git a/app/config/messagingProviders.php b/app/config/messagingProviders.php index 1d3ba8ed60..a33665196b 100644 --- a/app/config/messagingProviders.php +++ b/app/config/messagingProviders.php @@ -1,300 +1,300 @@ [ - 'mailchimp' => [ - 'name' => 'Mailchimp', - 'developers' => 'https://mailchimp.com/developer/marketing/api/', - 'icon' => 'icon-mailchimp', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'mailgun' => [ - 'name' => 'Mailgun', - 'developers' => 'https://documentation.mailgun.com/', - 'icon' => 'icon-mailgun', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'mailjet' => [ - 'name' => 'Mailjet', - 'developers' => 'https://dev.mailjet.com/', - 'icon' => 'icon-mailjet', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'postmark' => [ - 'name' => 'Postmark', - 'developers' => 'https://postmarkapp.com/developer', - 'icon' => 'icon-postmark', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sendgrid' => [ - 'name' => 'Sendgrid', - 'developers' => 'https://docs.sendgrid.com/api-reference/how-to-use-the-sendgrid-v3-api/', - 'icon' => 'icon-sendgrid', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sendinblue' => [ - 'name' => 'SendinBlue', - 'developers' => 'https://developers.sendinblue.com/', - 'icon' => 'icon-sendinblue', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'mailslurp' => [ - 'name' => 'MailSlurp', - 'developers' => 'https://www.mailslurp.com/docs/', - 'icon' => 'icon-mailslurp', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'elasticemail' => [ - 'name' => 'ElasticEmail', - 'developers' => 'https://api.elasticemail.com/public/help', - 'icon' => 'icon-elasticemail', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'ses' => [ - 'name' => 'SES', - 'developers' => 'https://docs.aws.amazon.com/ses/latest/APIReference/', - 'icon' => 'icon-ses', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], + 'email' => [ + 'mailchimp' => [ + 'name' => 'Mailchimp', + 'developers' => 'https://mailchimp.com/developer/marketing/api/', + 'icon' => 'icon-mailchimp', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, ], - 'sms' => [ - 'africastalking' => [ - 'name' => 'Africa\'s Talking', - 'developers' => 'https://developers.africastalking.com/', - 'icon' => 'icon-africastalking', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'clickatell' => [ - 'name' => 'Clickatell', - 'developers' => 'https://www.clickatell.com/developers/api-docs/', - 'icon' => 'icon-clickatell', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'infobip' => [ - 'name' => 'Infobip', - 'developers' => 'https://www.infobip.com/docs/', - 'icon' => 'icon-infobip', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'msg91' => [ - 'name' => 'Msg91', - 'developers' => 'https://docs.msg91.com/reference/overview', - 'icon' => 'icon-msg91', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'plivo' => [ - 'name' => 'Plivo', - 'developers' => 'https://developers.plivo.com/', - 'icon' => 'icon-plivo', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sinch' => [ - 'name' => 'Sinch', - 'developers' => 'https://developers.sinch.com/', - 'icon' => 'icon-sinch', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'sms77' => [ - 'name' => 'Sms77', - 'developers' => 'https://sms77.io/docs/gateway/', - 'icon' => 'icon-sms77', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'telesign' => [ - 'name' => 'Telesign', - 'developers' => 'https://developer.telesign.com/enterprise/docs', - 'icon' => 'icon-telesign', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'textmagic' => [ - 'name' => 'TextMagic', - 'developers' => 'https://www.textmagic.com/docs/api/', - 'icon' => 'icon-twilio', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'twilio' => [ - 'name' => 'Twilio', - 'developers' => 'https://www.twilio.com/docs/sms', - 'icon' => 'icon-twilio', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'twilio-notify' => [ - 'name' => 'Twilio Notify', - 'developers' => 'https://www.twilio.com/docs/notify', - 'icon' => 'icon-twilio', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'vonage' => [ - 'name' => 'Vonage', - 'developers' => 'https://developer.nexmo.com/', - 'icon' => 'icon-vonage', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], + 'mailgun' => [ + 'name' => 'Mailgun', + 'developers' => 'https://documentation.mailgun.com/', + 'icon' => 'icon-mailgun', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, ], - 'push' => [ - 'apns' => [ - 'name' => 'APNS', - 'developers' => 'https://developer.apple.com/documentation/usernotifications', - 'icon' => 'icon-apns', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'fcm' => [ - 'name' => 'FCM', - 'developers' => 'https://firebase.google.com/docs/cloud-messaging', - 'icon' => 'icon-fcm', - 'enabled' => true, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'one_signal' => [ - 'name' => 'OneSignal', - 'developers' => 'https://documentation.onesignal.com/docs', - 'icon' => 'icon-onesignal', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'pushbullet' => [ - 'name' => 'PushBullet', - 'developers' => 'https://docs.pushbullet.com/', - 'icon' => 'icon-pushbullet', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'pusher' => [ - 'name' => 'Pusher', - 'developers' => 'https://pusher.com/docs', - 'icon' => 'icon-pusher', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'pushwoosh' => [ - 'name' => 'Pushwoosh', - 'developers' => 'https://www.pushwoosh.com/docs/', - 'icon' => 'icon-pushwoosh', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'urban_airship' => [ - 'name' => 'Urban Airship', - 'developers' => 'https://docs.airship.com/api/', - 'icon' => 'icon-urbanairship', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], - 'web_push' => [ - 'name' => 'WebPush', - 'developers' => 'https://developer.mozilla.org/en-US/docs/Web/API/Push_API', - 'icon' => 'icon-webpush', - 'enabled' => false, - 'sandbox' => false, - 'form' => false, - 'beta' => false, - 'mock' => false, - ], + 'mailjet' => [ + 'name' => 'Mailjet', + 'developers' => 'https://dev.mailjet.com/', + 'icon' => 'icon-mailjet', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, ], + 'postmark' => [ + 'name' => 'Postmark', + 'developers' => 'https://postmarkapp.com/developer', + 'icon' => 'icon-postmark', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sendgrid' => [ + 'name' => 'Sendgrid', + 'developers' => 'https://docs.sendgrid.com/api-reference/how-to-use-the-sendgrid-v3-api/', + 'icon' => 'icon-sendgrid', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sendinblue' => [ + 'name' => 'SendinBlue', + 'developers' => 'https://developers.sendinblue.com/', + 'icon' => 'icon-sendinblue', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'mailslurp' => [ + 'name' => 'MailSlurp', + 'developers' => 'https://www.mailslurp.com/docs/', + 'icon' => 'icon-mailslurp', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'elasticemail' => [ + 'name' => 'ElasticEmail', + 'developers' => 'https://api.elasticemail.com/public/help', + 'icon' => 'icon-elasticemail', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'ses' => [ + 'name' => 'SES', + 'developers' => 'https://docs.aws.amazon.com/ses/latest/APIReference/', + 'icon' => 'icon-ses', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + ], + 'sms' => [ + 'africastalking' => [ + 'name' => 'Africa\'s Talking', + 'developers' => 'https://developers.africastalking.com/', + 'icon' => 'icon-africastalking', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'clickatell' => [ + 'name' => 'Clickatell', + 'developers' => 'https://www.clickatell.com/developers/api-docs/', + 'icon' => 'icon-clickatell', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'infobip' => [ + 'name' => 'Infobip', + 'developers' => 'https://www.infobip.com/docs/', + 'icon' => 'icon-infobip', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'msg91' => [ + 'name' => 'Msg91', + 'developers' => 'https://docs.msg91.com/reference/overview', + 'icon' => 'icon-msg91', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'plivo' => [ + 'name' => 'Plivo', + 'developers' => 'https://developers.plivo.com/', + 'icon' => 'icon-plivo', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sinch' => [ + 'name' => 'Sinch', + 'developers' => 'https://developers.sinch.com/', + 'icon' => 'icon-sinch', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'sms77' => [ + 'name' => 'Sms77', + 'developers' => 'https://sms77.io/docs/gateway/', + 'icon' => 'icon-sms77', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'telesign' => [ + 'name' => 'Telesign', + 'developers' => 'https://developer.telesign.com/enterprise/docs', + 'icon' => 'icon-telesign', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'textmagic' => [ + 'name' => 'TextMagic', + 'developers' => 'https://www.textmagic.com/docs/api/', + 'icon' => 'icon-twilio', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'twilio' => [ + 'name' => 'Twilio', + 'developers' => 'https://www.twilio.com/docs/sms', + 'icon' => 'icon-twilio', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'twilio-notify' => [ + 'name' => 'Twilio Notify', + 'developers' => 'https://www.twilio.com/docs/notify', + 'icon' => 'icon-twilio', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'vonage' => [ + 'name' => 'Vonage', + 'developers' => 'https://developer.nexmo.com/', + 'icon' => 'icon-vonage', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + ], + 'push' => [ + 'apns' => [ + 'name' => 'APNS', + 'developers' => 'https://developer.apple.com/documentation/usernotifications', + 'icon' => 'icon-apns', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'fcm' => [ + 'name' => 'FCM', + 'developers' => 'https://firebase.google.com/docs/cloud-messaging', + 'icon' => 'icon-fcm', + 'enabled' => true, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'one_signal' => [ + 'name' => 'OneSignal', + 'developers' => 'https://documentation.onesignal.com/docs', + 'icon' => 'icon-onesignal', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'pushbullet' => [ + 'name' => 'PushBullet', + 'developers' => 'https://docs.pushbullet.com/', + 'icon' => 'icon-pushbullet', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'pusher' => [ + 'name' => 'Pusher', + 'developers' => 'https://pusher.com/docs', + 'icon' => 'icon-pusher', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'pushwoosh' => [ + 'name' => 'Pushwoosh', + 'developers' => 'https://www.pushwoosh.com/docs/', + 'icon' => 'icon-pushwoosh', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'urban_airship' => [ + 'name' => 'Urban Airship', + 'developers' => 'https://docs.airship.com/api/', + 'icon' => 'icon-urbanairship', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + 'web_push' => [ + 'name' => 'WebPush', + 'developers' => 'https://developer.mozilla.org/en-US/docs/Web/API/Push_API', + 'icon' => 'icon-webpush', + 'enabled' => false, + 'sandbox' => false, + 'form' => false, + 'beta' => false, + 'mock' => false, + ], + ] ]; diff --git a/app/config/platforms.php b/app/config/platforms.php index 76dcbca50d..56103fad4a 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -24,7 +24,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'javascript', - 'source' => \realpath(__DIR__.'/../sdks/client-web'), + 'source' => \realpath(__DIR__ . '/../sdks/client-web'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-web.git', 'gitRepoName' => 'sdk-for-web', 'gitUserName' => 'appwrite', @@ -58,7 +58,7 @@ return [ 'source' => 'https://github.com/appwrite/todo-with-svelte', 'url' => 'https://appwrite-todo-with-svelte.vercel.app/', ], - ], + ] ], [ 'key' => 'flutter', @@ -72,7 +72,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'dart', - 'source' => \realpath(__DIR__.'/../sdks/client-flutter'), + 'source' => \realpath(__DIR__ . '/../sdks/client-flutter'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-flutter.git', 'gitRepoName' => 'sdk-for-flutter', 'gitUserName' => 'appwrite', @@ -90,7 +90,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'swift', - 'source' => \realpath(__DIR__.'/../sdks/client-apple'), + 'source' => \realpath(__DIR__ . '/../sdks/client-apple'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-apple.git', 'gitRepoName' => 'sdk-for-apple', 'gitUserName' => 'appwrite', @@ -125,7 +125,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'kotlin', - 'source' => \realpath(__DIR__.'/../sdks/client-android'), + 'source' => \realpath(__DIR__ . '/../sdks/client-android'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-android.git', 'gitRepoName' => 'sdk-for-android', 'gitUserName' => 'appwrite', @@ -147,7 +147,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'graphql', - 'source' => \realpath(__DIR__.'/../sdks/client-graphql'), + 'source' => \realpath(__DIR__ . '/../sdks/client-graphql'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', @@ -166,7 +166,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_CLIENT, 'prism' => 'http', - 'source' => \realpath(__DIR__.'/../sdks/client-rest'), + 'source' => \realpath(__DIR__ . '/../sdks/client-rest'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', @@ -194,7 +194,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_CONSOLE, 'prism' => 'javascript', - 'source' => \realpath(__DIR__.'/../sdks/console-web'), + 'source' => \realpath(__DIR__ . '/../sdks/console-web'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-console.git', 'gitBranch' => 'dev', 'gitRepoName' => 'sdk-for-console', @@ -212,7 +212,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_CONSOLE, 'prism' => 'bash', - 'source' => \realpath(__DIR__.'/../sdks/console-cli'), + 'source' => \realpath(__DIR__ . '/../sdks/console-cli'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-cli.git', 'gitRepoName' => 'sdk-for-cli', 'gitUserName' => 'appwrite', @@ -240,7 +240,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'javascript', - 'source' => \realpath(__DIR__.'/../sdks/server-nodejs'), + 'source' => \realpath(__DIR__ . '/../sdks/server-nodejs'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-node.git', 'gitRepoName' => 'sdk-for-node', 'gitUserName' => 'appwrite', @@ -258,7 +258,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'typescript', - 'source' => \realpath(__DIR__.'/../sdks/server-deno'), + 'source' => \realpath(__DIR__ . '/../sdks/server-deno'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-deno.git', 'gitRepoName' => 'sdk-for-deno', 'gitUserName' => 'appwrite', @@ -276,7 +276,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'php', - 'source' => \realpath(__DIR__.'/../sdks/server-php'), + 'source' => \realpath(__DIR__ . '/../sdks/server-php'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-php.git', 'gitRepoName' => 'sdk-for-php', 'gitUserName' => 'appwrite', @@ -294,7 +294,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'python', - 'source' => \realpath(__DIR__.'/../sdks/server-python'), + 'source' => \realpath(__DIR__ . '/../sdks/server-python'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-python.git', 'gitRepoName' => 'sdk-for-python', 'gitUserName' => 'appwrite', @@ -312,7 +312,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'ruby', - 'source' => \realpath(__DIR__.'/../sdks/server-ruby'), + 'source' => \realpath(__DIR__ . '/../sdks/server-ruby'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-ruby.git', 'gitRepoName' => 'sdk-for-ruby', 'gitUserName' => 'appwrite', @@ -330,7 +330,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'go', - 'source' => \realpath(__DIR__.'/../sdks/server-go'), + 'source' => \realpath(__DIR__ . '/../sdks/server-go'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-go.git', 'gitRepoName' => 'sdk-for-go', 'gitUserName' => 'appwrite', @@ -348,7 +348,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'java', - 'source' => \realpath(__DIR__.'/../sdks/server-java'), + 'source' => \realpath(__DIR__ . '/../sdks/server-java'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-java.git', 'gitRepoName' => 'sdk-for-java', 'gitUserName' => 'appwrite', @@ -366,7 +366,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'csharp', - 'source' => \realpath(__DIR__.'/../sdks/server-dotnet'), + 'source' => \realpath(__DIR__ . '/../sdks/server-dotnet'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-dotnet.git', 'gitRepoName' => 'sdk-for-dotnet', 'gitUserName' => 'appwrite', @@ -384,7 +384,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'dart', - 'source' => \realpath(__DIR__.'/../sdks/server-dart'), + 'source' => \realpath(__DIR__ . '/../sdks/server-dart'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-dart.git', 'gitRepoName' => 'sdk-for-dart', 'gitUserName' => 'appwrite', @@ -402,7 +402,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'kotlin', - 'source' => \realpath(__DIR__.'/../sdks/server-kotlin'), + 'source' => \realpath(__DIR__ . '/../sdks/server-kotlin'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-kotlin.git', 'gitRepoName' => 'sdk-for-kotlin', 'gitUserName' => 'appwrite', @@ -424,7 +424,7 @@ return [ 'hidden' => false, 'family' => APP_PLATFORM_SERVER, 'prism' => 'swift', - 'source' => \realpath(__DIR__.'/../sdks/server-swift'), + 'source' => \realpath(__DIR__ . '/../sdks/server-swift'), 'gitUrl' => 'git@github.com:appwrite/sdk-for-swift.git', 'gitRepoName' => 'sdk-for-swift', 'gitUserName' => 'appwrite', @@ -442,7 +442,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_SERVER, 'prism' => 'graphql', - 'source' => \realpath(__DIR__.'/../sdks/server-graphql'), + 'source' => \realpath(__DIR__ . '/../sdks/server-graphql'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', @@ -461,7 +461,7 @@ return [ 'hidden' => true, 'family' => APP_PLATFORM_SERVER, 'prism' => 'http', - 'source' => \realpath(__DIR__.'/../sdks/server-rest'), + 'source' => \realpath(__DIR__ . '/../sdks/server-rest'), 'gitUrl' => '', 'gitRepoName' => '', 'gitUserName' => '', diff --git a/app/config/regions.php b/app/config/regions.php index cc920bee82..0dc5fab1ed 100644 --- a/app/config/regions.php +++ b/app/config/regions.php @@ -5,5 +5,5 @@ return [ 'name' => 'Default', 'default' => true, 'disabled' => false, - ], + ] ]; diff --git a/app/config/roles.php b/app/config/roles.php index cf1827e25e..4bc85f7a28 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -25,7 +25,7 @@ $member = [ 'providers.write', 'providers.read', 'messages.write', - 'messages.read', + 'messages.read' ]; $admins = [ @@ -64,7 +64,7 @@ $admins = [ 'providers.write', 'providers.read', 'messages.write', - 'messages.read', + 'messages.read' ]; return [ diff --git a/app/config/runtimes.php b/app/config/runtimes.php index d249946d05..c24aaa109e 100644 --- a/app/config/runtimes.php +++ b/app/config/runtimes.php @@ -4,8 +4,8 @@ * List of Appwrite Cloud Functions supported runtimes */ -use Appwrite\Runtimes\Runtimes; use Utopia\App; +use Appwrite\Runtimes\Runtimes; $runtimes = new Runtimes('v2'); diff --git a/app/config/scopes.php b/app/config/scopes.php index 6dbc19d4aa..cf00654b1e 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -37,7 +37,7 @@ return [ // List of publicly visible scopes 'indexes.write' => [ 'description' => 'Access to create, update, and delete your project\'s database collection\'s indexes', ], - 'documents.read' => [ + 'documents.read' => [ 'description' => 'Access to read your project\'s database documents', ], 'documents.write' => [ @@ -111,5 +111,5 @@ return [ // List of publicly visible scopes ], 'targets.write' => [ 'description' => 'Access to create, update, and delete your project\'s targets', - ], + ] ]; diff --git a/app/config/services.php b/app/config/services.php index ee879eff94..f80431f784 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -66,8 +66,8 @@ return [ 'optional' => true, 'icon' => '/images/services/databases.png', 'globalAttributes' => [ - 'databaseId', - ], + 'databaseId' + ] ], 'locale' => [ 'key' => 'locale', @@ -237,5 +237,5 @@ return [ 'tests' => false, 'optional' => true, 'icon' => '/images/services/messaging.png', - ], + ] ]; diff --git a/app/config/usage.php b/app/config/usage.php index a0d3f9f725..2179bcce54 100644 --- a/app/config/usage.php +++ b/app/config/usage.php @@ -1,24 +1,24 @@ [ - 'period' => '1h', - 'limit' => 24, - 'factor' => 3600, - ], - '7d' => [ - 'period' => '1d', - 'limit' => 7, - 'factor' => 86400, - ], - '30d' => [ - 'period' => '1d', - 'limit' => 30, - 'factor' => 86400, - ], - '90d' => [ - 'period' => '1d', - 'limit' => 90, - 'factor' => 86400, - ], + '24h' => [ + 'period' => '1h', + 'limit' => 24, + 'factor' => 3600, + ], + '7d' => [ + 'period' => '1d', + 'limit' => 7, + 'factor' => 86400, + ], + '30d' => [ + 'period' => '1d', + 'limit' => 30, + 'factor' => 86400, + ], + '90d' => [ + 'period' => '1d', + 'limit' => 90, + 'factor' => 86400, + ], ]; diff --git a/app/config/variables.php b/app/config/variables.php index 136ecec5de..c04ba339e5 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -14,7 +14,7 @@ return [ 'default' => 'production', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_LOCALE', @@ -23,7 +23,7 @@ return [ 'default' => 'en', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_OPTIONS_ABUSE', @@ -32,7 +32,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_OPTIONS_FORCE_HTTPS', @@ -41,7 +41,7 @@ return [ 'default' => 'disabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_OPENSSL_KEY_V1', @@ -50,7 +50,7 @@ return [ 'default' => 'your-secret-key', 'required' => true, 'question' => 'Choose a secret API key, make sure to make a backup of your key in a secure location', - 'filter' => 'token', + 'filter' => 'token' ], [ 'name' => '_APP_DOMAIN', @@ -59,7 +59,7 @@ return [ 'default' => 'localhost', 'required' => true, 'question' => 'Enter your Appwrite hostname', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DOMAIN_TARGET', @@ -67,8 +67,8 @@ return [ 'introduction' => '', 'default' => 'localhost', 'required' => true, - 'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.'.PHP_EOL.'You can use the same value as used for the Appwrite hostname.', - 'filter' => 'domainTarget', + 'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.' . PHP_EOL . 'You can use the same value as used for the Appwrite hostname.', + 'filter' => 'domainTarget' ], [ 'name' => '_APP_CONSOLE_WHITELIST_ROOT', @@ -77,7 +77,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_CONSOLE_WHITELIST_EMAILS', @@ -86,7 +86,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], // [ // 'name' => '_APP_CONSOLE_WHITELIST_DOMAINS', @@ -103,7 +103,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_CONSOLE_ROOT_SESSION', @@ -112,7 +112,7 @@ return [ 'default' => 'disabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SYSTEM_EMAIL_NAME', @@ -121,7 +121,7 @@ return [ 'default' => 'Appwrite', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SYSTEM_EMAIL_ADDRESS', @@ -130,7 +130,7 @@ return [ 'default' => 'team@appwrite.io', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SYSTEM_RESPONSE_FORMAT', @@ -139,7 +139,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', @@ -148,7 +148,7 @@ return [ 'default' => 'certs@appwrite.io', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_USAGE_STATS', @@ -157,7 +157,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_LOGGING_PROVIDER', @@ -166,7 +166,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_LOGGING_CONFIG', @@ -175,7 +175,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_USAGE_AGGREGATION_INTERVAL', @@ -184,7 +184,7 @@ return [ 'default' => '30', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_USAGE_TIMESERIES_INTERVAL', @@ -193,7 +193,7 @@ return [ 'default' => '30', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_USAGE_DATABASE_INTERVAL', @@ -202,7 +202,7 @@ return [ 'default' => '900', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_WORKER_PER_CORE', @@ -211,7 +211,7 @@ return [ 'default' => 6, 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_CONSOLE_INVITES', @@ -220,7 +220,7 @@ return [ 'default' => 'enabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], ], ], @@ -235,7 +235,7 @@ return [ 'default' => 'redis', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_REDIS_PORT', @@ -244,7 +244,7 @@ return [ 'default' => '6379', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_REDIS_USER', @@ -253,7 +253,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_REDIS_PASS', @@ -262,7 +262,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], ], ], @@ -277,7 +277,7 @@ return [ 'default' => 'mariadb', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DB_PORT', @@ -286,7 +286,7 @@ return [ 'default' => '3306', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DB_SCHEMA', @@ -295,7 +295,7 @@ return [ 'default' => 'appwrite', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DB_USER', @@ -304,7 +304,7 @@ return [ 'default' => 'user', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DB_PASS', @@ -313,7 +313,7 @@ return [ 'default' => 'password', 'required' => false, 'question' => '', - 'filter' => 'password', + 'filter' => 'password' ], [ 'name' => '_APP_DB_ROOT_PASS', @@ -322,7 +322,7 @@ return [ 'default' => 'rootsecretpassword', 'required' => false, 'question' => '', - 'filter' => 'password', + 'filter' => 'password' ], [ 'name' => '_APP_CONNECTIONS_MAX', @@ -331,26 +331,26 @@ return [ 'default' => 251, 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], - // [ - // 'name' => '_APP_CONNECTIONS_DB_PROJECT', - // 'description' => 'A list of comma-separated key value pairs representing Project DBs where key is the database name and value is the DSN connection string.', - // 'introduction' => 'TBD', - // 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', - // 'required' => true, - // 'question' => '', - // 'filter' => '' - // ], - // [ - // 'name' => '_APP_CONNECTIONS_DB_CONSOLE', - // 'description' => 'A key value pair representing the Console DB where key is the database name and value is the DSN connection string.', - // 'introduction' => 'TBD', - // 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', - // 'required' => true, - // 'question' => '', - // 'filter' => '' - // ] +// [ +// 'name' => '_APP_CONNECTIONS_DB_PROJECT', +// 'description' => 'A list of comma-separated key value pairs representing Project DBs where key is the database name and value is the DSN connection string.', +// 'introduction' => 'TBD', +// 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', +// 'required' => true, +// 'question' => '', +// 'filter' => '' +// ], +// [ +// 'name' => '_APP_CONNECTIONS_DB_CONSOLE', +// 'description' => 'A key value pair representing the Console DB where key is the database name and value is the DSN connection string.', +// 'introduction' => 'TBD', +// 'default' => 'db_fra1_01=mysql://user:password@mariadb:3306/appwrite', +// 'required' => true, +// 'question' => '', +// 'filter' => '' +// ] ], ], [ @@ -364,7 +364,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SMTP_PORT', @@ -373,7 +373,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SMTP_SECURE', @@ -382,7 +382,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SMTP_USERNAME', @@ -391,7 +391,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SMTP_PASSWORD', @@ -400,7 +400,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], ], ], @@ -415,7 +415,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_SMS_FROM', @@ -424,7 +424,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], ], ], @@ -439,7 +439,7 @@ return [ 'default' => '30000000', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_STORAGE_PREVIEW_LIMIT', @@ -448,7 +448,7 @@ return [ 'default' => '20000000', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_STORAGE_ANTIVIRUS', @@ -457,7 +457,7 @@ return [ 'default' => 'disabled', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_STORAGE_ANTIVIRUS_HOST', @@ -466,7 +466,7 @@ return [ 'default' => 'clamav', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_STORAGE_ANTIVIRUS_PORT', @@ -475,7 +475,7 @@ return [ 'default' => '3310', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_CONNECTIONS_STORAGE', @@ -666,7 +666,7 @@ return [ 'default' => '30000000', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_TIMEOUT', @@ -675,7 +675,7 @@ return [ 'default' => '900', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT', @@ -684,7 +684,7 @@ return [ 'default' => '900', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_CONTAINERS', @@ -693,7 +693,7 @@ return [ 'default' => '10', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_CPUS', @@ -702,7 +702,7 @@ return [ 'default' => '0', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_MEMORY', @@ -711,7 +711,7 @@ return [ 'default' => '0', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_MEMORY_SWAP', @@ -720,16 +720,16 @@ return [ 'default' => '0', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_RUNTIMES', - 'description' => "This option allows you to enable or disable runtime environments for cloud functions. Disable unused runtimes to save disk space.\n\nTo enable cloud function runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: ".\implode(', ', \array_keys(Config::getParam('runtimes'))), + 'description' => "This option allows you to enable or disable runtime environments for cloud functions. Disable unused runtimes to save disk space.\n\nTo enable cloud function runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))), 'introduction' => '0.8.0', 'default' => 'node-16.0,php-8.0,python-3.9,ruby-3.0', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_EXECUTOR_SECRET', @@ -738,7 +738,7 @@ return [ 'default' => 'your-secret-key', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_EXECUTOR_HOST', @@ -747,7 +747,7 @@ return [ 'default' => 'http://appwrite-executor/v1', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_EXECUTOR_RUNTIME_NETWORK', @@ -756,7 +756,7 @@ return [ 'default' => 'appwrite_runtimes', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_ENVS', @@ -765,7 +765,7 @@ return [ 'default' => 'node-16.0,php-7.4,python-3.9,ruby-3.0', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_INACTIVE_THRESHOLD', @@ -774,7 +774,7 @@ return [ 'default' => '60', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => 'DOCKERHUB_PULL_USERNAME', @@ -783,7 +783,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => 'DOCKERHUB_PULL_PASSWORD', @@ -792,7 +792,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => 'DOCKERHUB_PULL_EMAIL', @@ -801,7 +801,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => 'OPEN_RUNTIMES_NETWORK', @@ -810,7 +810,7 @@ return [ 'default' => 'appwrite_runtimes', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_RUNTIMES_NETWORK', @@ -819,7 +819,7 @@ return [ 'default' => 'runtimes', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DOCKER_HUB_USERNAME', @@ -828,7 +828,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_DOCKER_HUB_PASSWORD', @@ -837,7 +837,7 @@ return [ 'default' => '', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_FUNCTIONS_MAINTENANCE_INTERVAL', @@ -846,7 +846,7 @@ return [ 'default' => '60', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], ], ], @@ -861,7 +861,7 @@ return [ 'default' => '86400', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_MAINTENANCE_RETENTION_CACHE', @@ -870,7 +870,7 @@ return [ 'default' => '2592000', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_MAINTENANCE_RETENTION_EXECUTION', @@ -879,7 +879,7 @@ return [ 'default' => '1209600', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_MAINTENANCE_RETENTION_AUDIT', @@ -888,7 +888,7 @@ return [ 'default' => '1209600', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_MAINTENANCE_RETENTION_ABUSE', @@ -897,7 +897,7 @@ return [ 'default' => '86400', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_MAINTENANCE_RETENTION_USAGE_HOURLY', @@ -906,7 +906,7 @@ return [ 'default' => '8640000', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_MAINTENANCE_RETENTION_SCHEDULES', @@ -915,8 +915,8 @@ return [ 'default' => '86400', 'required' => false, 'question' => '', - 'filter' => '', - ], + 'filter' => '' + ] ], ], [ @@ -930,7 +930,7 @@ return [ 'default' => '10', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_GRAPHQL_MAX_COMPLEXITY', @@ -939,7 +939,7 @@ return [ 'default' => '250', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], [ 'name' => '_APP_GRAPHQL_MAX_DEPTH', @@ -948,7 +948,7 @@ return [ 'default' => '3', 'required' => false, 'question' => '', - 'filter' => '', + 'filter' => '' ], ], ], diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 8f9fc34635..46acd2efdb 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4,9 +4,6 @@ use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; use Appwrite\Auth\OAuth2\Exception as OAuth2Exception; use Appwrite\Auth\Validator\Password; -use Appwrite\Auth\Validator\PasswordDictionary; -use Appwrite\Auth\Validator\PasswordHistory; -use Appwrite\Auth\Validator\PersonalData; use Appwrite\Auth\Validator\Phone; use Appwrite\Detector\Detector; use Appwrite\Event\Event; @@ -14,11 +11,16 @@ use Appwrite\Event\Mail; use Appwrite\Event\Phone as EventPhone; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; +use Utopia\Validator\Host; +use Utopia\Validator\URL; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Template\Template; use Appwrite\URL\URL as URLParser; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; +use Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -26,25 +28,23 @@ use Utopia\App; use Utopia\Audit\Audit as EventAudit; use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\DateTime; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; use Utopia\Database\Query; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; -use Utopia\Validator\Host; use Utopia\Validator\Text; -use Utopia\Validator\URL; use Utopia\Validator\WhiteList; +use Appwrite\Auth\Validator\PasswordHistory; +use Appwrite\Auth\Validator\PasswordDictionary; +use Appwrite\Auth\Validator\PersonalData; $oauthDefaultSuccess = '/auth/oauth2/success'; $oauthDefaultFailure = '/auth/oauth2/failure'; @@ -77,19 +77,20 @@ App::post('/v1/account/invite') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $email, string $password, string $name, string $code, Request $request, Response $response, Document $project, Database $dbForProject, Event $events) { + if ($project->getId() !== 'console') { throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN); } $email = \strtolower($email); - $whitelistCodes = (! empty(App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null)) : []; + $whitelistCodes = (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_CODES', null)) : []; if (empty($whitelistCodes)) { throw new Exception(Exception::GENERAL_CODES_DISABLED); } - if (! empty($whitelistCodes) && ! \in_array($code, $whitelistCodes)) { + if (!empty($whitelistCodes) && !\in_array($code, $whitelistCodes)) { throw new Exception(Exception::USER_INVALID_CODE); } @@ -105,7 +106,7 @@ App::post('/v1/account/invite') try { $userId = $userId == 'unique()' ? ID::unique() : $userId; - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([ + $user = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ Permission::read(Role::any()), @@ -126,7 +127,7 @@ App::post('/v1/account/invite') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]), + 'search' => implode(' ', [$userId, $email, $name]) ]))); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); @@ -176,11 +177,11 @@ App::post('/v1/account') $whitelistEmails = $project->getAttribute('authWhitelistEmails'); $whitelistIPs = $project->getAttribute('authWhitelistIPs'); - if (! empty($whitelistEmails) && ! \in_array($email, $whitelistEmails) && ! \in_array(strtoupper($email), $whitelistEmails)) { + if (!empty($whitelistEmails) && !\in_array($email, $whitelistEmails) && !\in_array(strtoupper($email), $whitelistEmails)) { throw new Exception(Exception::USER_EMAIL_NOT_WHITELISTED); } - if (! empty($whitelistIPs) && ! \in_array($request->getIP(), $whitelistIPs)) { + if (!empty($whitelistIPs) && !\in_array($request->getIP(), $whitelistIPs)) { throw new Exception(Exception::USER_IP_NOT_WHITELISTED); } } @@ -199,13 +200,13 @@ App::post('/v1/account') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($userId, $email, $name, null); - if (! $personalDataValidator->isValid($password)) { + if (!$personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } @@ -239,7 +240,7 @@ App::post('/v1/account') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), // Add this here to make sure it's returned in the response ]); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn() => $dbForProject->createDocument('users', $user)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } @@ -285,6 +286,7 @@ App::post('/v1/account/sessions/email') ->inject('geodb') ->inject('events') ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $events) { + $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -292,7 +294,7 @@ App::post('/v1/account/sessions/email') Query::equal('email', [$email]), ]); - if (! $profile || empty($profile->getAttribute('passwordUpdate')) || ! Auth::passwordVerify($password, $profile->getAttribute('password'), $profile->getAttribute('hash'), $profile->getAttribute('hashOptions'))) { + if (!$profile || empty($profile->getAttribute('passwordUpdate')) || !Auth::passwordVerify($password, $profile->getAttribute('password'), $profile->getAttribute('hash'), $profile->getAttribute('hashOptions'))) { throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -344,26 +346,31 @@ App::post('/v1/account/sessions/email') Permission::delete(Role::user($user->getId())), ])); - if (! Config::getParam('domainVerification')) { + + if (!Config::getParam('domainVerification')) { $response - ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); + ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) + ; } $response - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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); + ->setStatusCode(Response::STATUS_CODE_CREATED) + ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire); + ->setAttribute('expire', $expire) + ; $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()); + ->setParam('sessionId', $session->getId()) + ; $response->dynamic($session, Response::MODEL_SESSION); }); @@ -371,7 +378,7 @@ App::post('/v1/account/sessions/email') App::get('/v1/account/sessions/oauth2/:provider') ->desc('Create OAuth2 Session') ->groups(['api', 'account']) - ->label('error', __DIR__.'/../../views/general/error.phtml') + ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'public') ->label('sdk.auth', []) ->label('sdk.namespace', 'account') @@ -382,47 +389,48 @@ App::get('/v1/account/sessions/oauth2/:provider') ->label('sdk.methodType', 'webAuth') ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') - ->param('provider', '', new WhiteList(\array_keys(Config::getParam('authProviders')), true), 'OAuth2 Provider. Currently, supported providers are: '.\implode(', ', \array_keys(\array_filter(Config::getParam('authProviders'), fn ($node) => (! $node['mock'])))).'.') - ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. 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.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. 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.', true, ['clients']) - ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' scopes are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long.', true) + ->param('provider', '', new WhiteList(\array_keys(Config::getParam('authProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('authProviders'), fn($node) => (!$node['mock'])))) . '.') + ->param('success', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. 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.', true, ['clients']) + ->param('failure', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. 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.', true, ['clients']) + ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('request') ->inject('response') ->inject('project') ->action(function (string $provider, string $success, string $failure, array $scopes, Request $request, Response $response, Document $project) use ($oauthDefaultSuccess, $oauthDefaultFailure) { + $protocol = $request->getProtocol(); - $callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId(); - $providerEnabled = $project->getAttribute('authProviders', [])[$provider.'Enabled'] ?? false; + $callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId(); + $providerEnabled = $project->getAttribute('authProviders', [])[$provider . 'Enabled'] ?? false; - if (! $providerEnabled) { - throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your '.APP_NAME.' console to continue.'); + if (!$providerEnabled) { + throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your ' . APP_NAME . ' console to continue.'); } - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; - if (! empty($appSecret) && isset($appSecret['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$appSecret['version']); + if (!empty($appSecret) && isset($appSecret['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']); $appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, \hex2bin($appSecret['iv']), \hex2bin($appSecret['tag'])); } if (empty($appId) || empty($appSecret)) { - throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please configure the provider app ID and app secret key from your '.APP_NAME.' console to continue.'); + throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.'); } - $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); - if (! \class_exists($className)) { + if (!\class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } if (empty($success)) { - $success = $protocol.'://'.$request->getHostname().$oauthDefaultSuccess; + $success = $protocol . '://' . $request->getHostname() . $oauthDefaultSuccess; } if (empty($failure)) { - $failure = $protocol.'://'.$request->getHostname().$oauthDefaultFailure; + $failure = $protocol . '://' . $request->getHostname() . $oauthDefaultFailure; } $oauth2 = new $className($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure], $scopes); @@ -436,7 +444,7 @@ App::get('/v1/account/sessions/oauth2/:provider') App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->desc('OAuth2 Callback') ->groups(['account']) - ->label('error', __DIR__.'/../../views/general/error.phtml') + ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'public') ->label('docs', false) ->param('projectId', '', new Text(1024), 'Project ID.') @@ -448,26 +456,27 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->inject('request') ->inject('response') ->action(function (string $projectId, string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response) { + $domain = $request->getHostname(); $protocol = $request->getProtocol(); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') - ->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?' - .\http_build_query([ + ->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?' + . \http_build_query([ 'project' => $projectId, 'code' => $code, 'state' => $state, 'error' => $error, - 'error_description' => $error_description, + 'error_description' => $error_description ])); }); App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->desc('OAuth2 Callback') ->groups(['account']) - ->label('error', __DIR__.'/../../views/general/error.phtml') + ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'public') ->label('origin', '*') ->label('docs', false) @@ -480,26 +489,27 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->inject('request') ->inject('response') ->action(function (string $projectId, string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response) { + $domain = $request->getHostname(); $protocol = $request->getProtocol(); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') - ->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?' - .\http_build_query([ + ->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?' + . \http_build_query([ 'project' => $projectId, 'code' => $code, 'state' => $state, 'error' => $error, - 'error_description' => $error_description, + 'error_description' => $error_description ])); }); App::get('/v1/account/sessions/oauth2/:provider/redirect') ->desc('OAuth2 Redirect') ->groups(['api', 'account', 'session']) - ->label('error', __DIR__.'/../../views/general/error.phtml') + ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('event', 'users.[userId].sessions.[sessionId].create') ->label('scope', 'public') ->label('audits.event', 'session.create') @@ -521,17 +531,18 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('geodb') ->inject('events') ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $events) use ($oauthDefaultSuccess) { + $protocol = $request->getProtocol(); - $callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId(); + $callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId(); $defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => '']; $validateURL = new URL(); - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; - $providerEnabled = $project->getAttribute('authProviders', [])[$provider.'Enabled'] ?? false; + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; + $providerEnabled = $project->getAttribute('authProviders', [])[$provider . 'Enabled'] ?? false; - $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); - if (! \class_exists($className)) { + if (!\class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } @@ -541,7 +552,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') /** @var Appwrite\Auth\OAuth2 $oauth2 */ $oauth2 = new $className($appId, $appSecret, $callback); - if (! empty($state)) { + if (!empty($state)) { try { $state = \array_merge($defaultState, $oauth2->parseState($state)); } catch (\Exception $exception) { @@ -551,25 +562,25 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $state = $defaultState; } - if (! $validateURL->isValid($state['success'])) { + if (!$validateURL->isValid($state['success'])) { throw new Exception(Exception::PROJECT_INVALID_SUCCESS_URL); } - if (! empty($state['failure']) && ! $validateURL->isValid($state['failure'])) { + if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) { throw new Exception(Exception::PROJECT_INVALID_FAILURE_URL); } $failure = []; - if (! empty($state['failure'])) { + if (!empty($state['failure'])) { $failure = URLParser::parse($state['failure']); } $failureRedirect = (function (string $type, ?string $message = null, ?int $code = null) use ($failure, $response) { $exception = new Exception($type, $message, $code); - if (! empty($failure)) { + if (!empty($failure)) { $query = URLParser::parseQuery($failure['query']); $query['error'] = json_encode([ 'message' => $exception->getMessage(), 'type' => $exception->getType(), - 'code' => ! \is_null($code) ? $code : $exception->getCode(), + 'code' => !\is_null($code) ? $code : $exception->getCode(), ]); $failure['query'] = URLParser::unparseQuery($query); $response->redirect(URLParser::unparse($failure), 301); @@ -578,14 +589,14 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') throw $exception; }); - if (! $providerEnabled) { - $failureRedirect(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your '.APP_NAME.' console to continue.'); + if (!$providerEnabled) { + $failureRedirect(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your ' . APP_NAME . ' console to continue.'); } - if (! empty($error)) { - $message = 'The '.$providerName.' OAuth2 provider returned an error: '.$error; - if (! empty($error_description)) { - $message .= ': '.$error_description; + if (!empty($error)) { + $message = 'The ' . $providerName . ' OAuth2 provider returned an error: ' . $error; + if (!empty($error_description)) { + $message .= ': ' . $error_description; } $failureRedirect(Exception::USER_OAUTH2_PROVIDER_ERROR, $message); } @@ -594,8 +605,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $failureRedirect(Exception::USER_OAUTH2_PROVIDER_ERROR, 'Missing OAuth2 code. Please contact the Appwrite team for additional support.'); } - if (! empty($appSecret) && isset($appSecret['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$appSecret['version']); + if (!empty($appSecret) && isset($appSecret['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']); $appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, \hex2bin($appSecret['iv']), \hex2bin($appSecret['tag'])); } @@ -610,7 +621,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } catch (OAuth2Exception $ex) { $failureRedirect( $ex->getType(), - 'Failed to obtain access token. The '.$providerName.' OAuth2 provider returned an error: '.$ex->getMessage(), + 'Failed to obtain access token. The ' . $providerName . ' OAuth2 provider returned an error: ' . $ex->getMessage(), $ex->getCode(), ); } @@ -624,14 +635,14 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $email = $oauth2->getUserEmail($accessToken); // Check if this identity is connected to a different user - if (! $user->isEmpty()) { + if (!$user->isEmpty()) { $userId = $user->getId(); $identitiesWithMatchingEmail = $dbForProject->find('identities', [ Query::equal('providerEmail', [$email]), Query::notEqual('userId', $userId), ]); - if (! empty($identitiesWithMatchingEmail)) { + if (!empty($identitiesWithMatchingEmail)) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } @@ -642,7 +653,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') if ($current) { // Delete current session of new one. $currentDocument = $dbForProject->getDocument('sessions', $current); - if (! $currentDocument->isEmpty()) { + if (!$currentDocument->isEmpty()) { $dbForProject->deleteDocument('sessions', $currentDocument->getId()); $dbForProject->deleteCachedDocument('users', $user->getId()); } @@ -653,7 +664,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('provider', [$provider]), Query::equal('providerUid', [$oauth2ID]), ]); - if ($session !== false && ! $session->isEmpty()) { + if ($session !== false && !$session->isEmpty()) { $user->setAttributes($dbForProject->getDocument('users', $session->getAttribute('userId'))->getArrayCopy()); } } @@ -671,7 +682,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $userWithEmail = $dbForProject->findOne('users', [ Query::equal('email', [$email]), ]); - if ($userWithEmail !== false && ! $userWithEmail->isEmpty()) { + if ($userWithEmail !== false && !$userWithEmail->isEmpty()) { $user->setAttributes($userWithEmail->getArrayCopy()); } @@ -682,7 +693,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('providerUid', [$oauth2ID]), ]); - if ($identity !== false && ! $identity->isEmpty()) { + if ($identity !== false && !$identity->isEmpty()) { $user = $dbForProject->getDocument('users', $identity->getAttribute('userId')); } } @@ -702,7 +713,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } @@ -729,9 +740,9 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]), + 'search' => implode(' ', [$userId, $email, $name]) ]); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn() => $dbForProject->createDocument('users', $user)); } catch (Duplicate $th) { $failureRedirect(Exception::USER_ALREADY_EXISTS); } @@ -758,7 +769,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('providerEmail', [$email]), Query::notEqual('userId', $user->getId()), ]); - if (! empty($identitiesWithMatchingEmail)) { + if (!empty($identitiesWithMatchingEmail)) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } @@ -776,13 +787,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); } @@ -801,7 +812,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'providerUid' => $oauth2ID, 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry), + 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -817,7 +828,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } $user - ->setAttribute('status', true); + ->setAttribute('status', true) + ; Authorization::setRole(Role::user($user->getId())->toString()); @@ -836,9 +848,10 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $events ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()) - ->setPayload($response->output($session, Response::MODEL_SESSION)); + ->setPayload($response->output($session, Response::MODEL_SESSION)) + ; - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } @@ -857,9 +870,10 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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')) - ->redirect($state['success']); + ->redirect($state['success']) + ; }); App::get('/v1/account/identities') @@ -875,11 +889,12 @@ App::get('/v1/account/identities') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) ->label('sdk.offline.model', '/account/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('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) ->inject('response') ->inject('user') ->inject('dbForProject') ->action(function (array $queries, Response $response, Document $user, Database $dbForProject) { + $queries = Query::parseQueries($queries); $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); @@ -929,6 +944,7 @@ App::delete('/v1/account/identities/:identityId') ->inject('response') ->inject('dbForProject') ->action(function (string $identityId, Response $response, Database $dbForProject) { + $identity = $dbForProject->getDocument('identities', $identityId); if ($identity->isEmpty()) { @@ -959,7 +975,7 @@ App::post('/v1/account/sessions/magic-url') ->label('abuse-key', 'url:{url},email:{param-email}') ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. 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.', true, ['clients']) + ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. 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.', true, ['clients']) ->inject('request') ->inject('response') ->inject('user') @@ -969,6 +985,7 @@ App::post('/v1/account/sessions/magic-url') ->inject('events') ->inject('mails') ->action(function (string $userId, string $email, string $url, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $events, Mail $mails) { + if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -978,7 +995,7 @@ App::post('/v1/account/sessions/magic-url') $isAppUser = Auth::isAppUser($roles); $result = $dbForProject->findOne('users', [Query::equal('email', [$email])]); - if ($result !== false && ! $result->isEmpty()) { + if ($result !== false && !$result->isEmpty()) { $user->setAttributes($result->getArrayCopy()); } else { $limit = $project->getAttribute('auths', [])['limit'] ?? 0; @@ -995,7 +1012,7 @@ App::post('/v1/account/sessions/magic-url') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } @@ -1021,7 +1038,7 @@ App::post('/v1/account/sessions/magic-url') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email]), + 'search' => implode(' ', [$userId, $email]) ]); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); @@ -1053,7 +1070,7 @@ App::post('/v1/account/sessions/magic-url') $dbForProject->deleteCachedDocument('users', $user->getId()); if (empty($url)) { - $url = $request->getProtocol().'://'.$request->getHostname().'/auth/magic-url'; + $url = $request->getProtocol() . '://' . $request->getHostname() . '/auth/magic-url'; } $url = Template::parseURL($url); @@ -1061,12 +1078,12 @@ App::post('/v1/account/sessions/magic-url') $url = Template::unParseURL($url); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $project->getAttribute('name')); - $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); - $subject = $locale->getText('emails.magicSession.subject'); + $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); + $subject = $locale->getText("emails.magicSession.subject"); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.magicSession-'.$locale->default] ?? []; - if ($smtpEnabled && ! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.magicSession-' . $locale->default] ?? []; + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message'] ?? $body; $subject = $customTemplate['subject'] ?? $subject; $from = $customTemplate['senderName'] ?? $from; @@ -1074,13 +1091,13 @@ App::post('/v1/account/sessions/magic-url') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText('emails.magicSession.hello')) + ->setParam('{{hello}}', $locale->getText("emails.magicSession.hello")) ->setParam('{{name}}', '') - ->setParam('{{body}}', $locale->getText('emails.magicSession.body')) + ->setParam('{{body}}', $locale->getText("emails.magicSession.body")) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText('emails.magicSession.footer')) - ->setParam('{{thanks}}', $locale->getText('emails.magicSession.thanks')) - ->setParam('{{signature}}', $locale->getText('emails.magicSession.signature')) + ->setParam('{{footer}}', $locale->getText("emails.magicSession.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.magicSession.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.magicSession.signature")) ->setParam('{{project}}', $project->getAttribute('name')) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -1094,7 +1111,8 @@ App::post('/v1/account/sessions/magic-url') ->setBody($body) ->setFrom($from) ->setRecipient($user->getAttribute('email')) - ->trigger(); + ->trigger() + ; $events->setPayload( $response->output( @@ -1108,7 +1126,8 @@ App::post('/v1/account/sessions/magic-url') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN); + ->dynamic($token, Response::MODEL_TOKEN) + ; }); App::put('/v1/account/sessions/magic-url') @@ -1139,8 +1158,10 @@ App::put('/v1/account/sessions/magic-url') ->inject('geodb') ->inject('events') ->action(function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $events) { + /** @var Utopia\Database\Document $user */ - $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + + $userFromRequest = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1148,7 +1169,7 @@ App::put('/v1/account/sessions/magic-url') $token = Auth::tokenVerify($userFromRequest->getAttribute('tokens', []), Auth::TOKEN_TYPE_MAGIC_URL, $secret); - if (! $token) { + if (!$token) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -1206,25 +1227,28 @@ App::put('/v1/account/sessions/magic-url') $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()); + ->setParam('sessionId', $session->getId()) + ; - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $protocol = $request->getProtocol(); $response - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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); + ->setStatusCode(Response::STATUS_CODE_CREATED) + ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire); + ->setAttribute('expire', $expire) + ; $response->dynamic($session, Response::MODEL_SESSION); }); @@ -1257,6 +1281,7 @@ App::post('/v1/account/sessions/phone') ->inject('messaging') ->inject('locale') ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, EventPhone $messaging, Locale $locale) { + if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -1266,7 +1291,7 @@ App::post('/v1/account/sessions/phone') $isAppUser = Auth::isAppUser($roles); $result = $dbForProject->findOne('users', [Query::equal('phone', [$phone])]); - if ($result !== false && ! $result->isEmpty()) { + if ($result !== false && !$result->isEmpty()) { $user->setAttributes($result->getArrayCopy()); } else { $limit = $project->getAttribute('auths', [])['limit'] ?? 0; @@ -1300,7 +1325,7 @@ App::post('/v1/account/sessions/phone') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $phone]), + 'search' => implode(' ', [$userId, $phone]) ]); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); @@ -1331,10 +1356,10 @@ App::post('/v1/account/sessions/phone') $dbForProject->deleteCachedDocument('users', $user->getId()); - $message = Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl'); + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.login-'.$locale->default] ?? []; - if (! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['sms.login-' . $locale->default] ?? []; + if (!empty($customTemplate)) { $message = $customTemplate['message'] ?? $message; } @@ -1358,7 +1383,8 @@ App::post('/v1/account/sessions/phone') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN); + ->dynamic($token, Response::MODEL_TOKEN) + ; }); App::put('/v1/account/sessions/phone') @@ -1386,7 +1412,8 @@ App::put('/v1/account/sessions/phone') ->inject('geodb') ->inject('events') ->action(function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $events) { - $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + + $userFromRequest = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1394,7 +1421,7 @@ App::put('/v1/account/sessions/phone') $token = Auth::phoneTokenVerify($userFromRequest->getAttribute('tokens', []), $secret); - if (! $token) { + if (!$token) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -1450,25 +1477,28 @@ App::put('/v1/account/sessions/phone') $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()); + ->setParam('sessionId', $session->getId()) + ; - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $protocol = $request->getProtocol(); $response - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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); + ->setStatusCode(Response::STATUS_CODE_CREATED) + ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire); + ->setAttribute('expire', $expire) + ; $response->dynamic($session, Response::MODEL_SESSION); }); @@ -1500,13 +1530,14 @@ App::post('/v1/account/sessions/anonymous') ->inject('geodb') ->inject('events') ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $events) { + $protocol = $request->getProtocol(); if ('console' === $project->getId()) { throw new Exception(Exception::USER_ANONYMOUS_CONSOLE_PROHIBITED, 'Failed to create anonymous user'); } - if (! $user->isEmpty()) { + if (!$user->isEmpty()) { throw new Exception(Exception::USER_SESSION_ALREADY_EXISTS, 'Cannot create an anonymous user when logged in'); } @@ -1544,7 +1575,7 @@ App::post('/v1/account/sessions/anonymous') 'memberships' => null, 'search' => $userId, ]); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn() => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; @@ -1571,33 +1602,36 @@ App::post('/v1/account/sessions/anonymous') Authorization::setRole(Role::user($user->getId())->toString()); - $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())), - ])); + $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())), + ])); $dbForProject->deleteCachedDocument('users', $user->getId()); $events ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()); + ->setParam('sessionId', $session->getId()) + ; - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $response - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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); + ->setStatusCode(Response::STATUS_CODE_CREATED) + ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', $expire); + ->setAttribute('expire', $expire) + ; $response->dynamic($session, Response::MODEL_SESSION); }); @@ -1620,6 +1654,8 @@ App::post('/v1/account/jwt') ->inject('user') ->inject('dbForProject') ->action(function (Response $response, Document $user, Database $dbForProject) { + + $sessions = $user->getAttribute('sessions', []); $current = new Document(); @@ -1638,13 +1674,13 @@ App::post('/v1/account/jwt') $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic(new Document(['jwt' => $jwt->encode([ - // 'uid' => 1, - // 'aud' => 'http://site.com', - // 'scopes' => ['user'], - // 'iss' => 'http://api.mysite.com', - 'userId' => $user->getId(), - 'sessionId' => $current->getId(), - ])]), Response::MODEL_JWT); + // 'uid' => 1, + // 'aud' => 'http://site.com', + // 'scopes' => ['user'], + // 'iss' => 'http://api.mysite.com', + 'userId' => $user->getId(), + 'sessionId' => $current->getId(), + ])]), Response::MODEL_JWT); }); App::get('/v1/account') @@ -1663,6 +1699,7 @@ App::get('/v1/account') ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { + $response->dynamic($user, Response::MODEL_ACCOUNT); }); @@ -1682,6 +1719,7 @@ App::get('/v1/account/prefs') ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { + $prefs = $user->getAttribute('prefs', []); $response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES); @@ -1704,12 +1742,13 @@ App::get('/v1/account/sessions') ->inject('locale') ->inject('project') ->action(function (Response $response, Document $user, Locale $locale, Document $project) { + $sessions = $user->getAttribute('sessions', []); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $current = Auth::sessionVerify($sessions, Auth::$secret, $authDuration); foreach ($sessions as $key => $session) {/** @var Document $session */ - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session->setAttribute('countryName', $countryName); $session->setAttribute('current', ($current == $session->getId()) ? true : false); @@ -1742,6 +1781,7 @@ App::get('/v1/account/logs') ->inject('geodb') ->inject('dbForProject') ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { + $queries = Query::parseQueries($queries); $grouped = Query::groupByType($queries); $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; @@ -1754,7 +1794,7 @@ App::get('/v1/account/logs') $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); @@ -1769,8 +1809,8 @@ App::get('/v1/account/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -1797,6 +1837,7 @@ App::get('/v1/account/targets') ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { + $targets = $user->getAttribute('targets', []); $response->dynamic(new Document([ @@ -1825,6 +1866,7 @@ App::get('/v1/account/sessions/:sessionId') ->inject('dbForProject') ->inject('project') ->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Database $dbForProject, Document $project) { + $sessions = $user->getAttribute('sessions', []); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $sessionId = ($sessionId === 'current') @@ -1833,12 +1875,13 @@ App::get('/v1/account/sessions/:sessionId') foreach ($sessions as $session) {/** @var Document $session */ if ($sessionId == $session->getId()) { - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret))) ->setAttribute('countryName', $countryName) - ->setAttribute('expire', DateTime::formatTz(DateTime::addSeconds(new \DateTime($session->getCreatedAt()), $authDuration))); + ->setAttribute('expire', DateTime::formatTz(DateTime::addSeconds(new \DateTime($session->getCreatedAt()), $authDuration))) + ; return $response->dynamic($session, Response::MODEL_SESSION); } @@ -1864,6 +1907,7 @@ App::get('/v1/account/targets/:targetId') ->inject('response') ->inject('user') ->action(function (string $targetId, Response $response, Document $user) { + $target = $user->find('$id', $targetId, 'targets'); if (empty($target)) { @@ -1896,6 +1940,7 @@ App::patch('/v1/account/name') ->inject('dbForProject') ->inject('events') ->action(function (string $name, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $events) { + $user->setAttribute('name', $name); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); @@ -1931,8 +1976,9 @@ App::patch('/v1/account/password') ->inject('dbForProject') ->inject('events') ->action(function (string $password, string $oldPassword, ?\DateTime $requestTimestamp, Response $response, Document $user, Document $project, Database $dbForProject, Event $events) { + // Check old password only if its an existing user. - if (! empty($user->getAttribute('passwordUpdate')) && ! Auth::passwordVerify($oldPassword, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions'))) { // 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); } @@ -1941,7 +1987,7 @@ App::patch('/v1/account/password') $history = $user->getAttribute('passwordHistory', []); if ($historyLimit > 0) { $validator = new PasswordHistory($history, $user->getAttribute('hash'), $user->getAttribute('hashOptions')); - if (! $validator->isValid($password)) { + if (!$validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -1951,7 +1997,7 @@ App::patch('/v1/account/password') if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($user->getId(), $user->getAttribute('email'), $user->getAttribute('name'), $user->getAttribute('phone')); - if (! $personalDataValidator->isValid($password)) { + if (!$personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } @@ -1998,8 +2044,8 @@ App::patch('/v1/account/email') $passwordUpdate = $user->getAttribute('passwordUpdate'); if ( - ! empty($passwordUpdate) && - ! Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) + !empty($passwordUpdate) && + !Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) ) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -2011,14 +2057,14 @@ App::patch('/v1/account/email') Query::equal('providerEmail', [$email]), Query::notEqual('userId', $user->getId()), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } $user ->setAttribute('email', $email) ->setAttribute('emailVerification', false) // After this user needs to confirm mail again -; + ; if (empty($passwordUpdate)) { $user @@ -2067,8 +2113,8 @@ App::patch('/v1/account/phone') $passwordUpdate = $user->getAttribute('passwordUpdate'); if ( - ! empty($passwordUpdate) && - ! Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) + !empty($passwordUpdate) && + !Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) ) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -2076,7 +2122,7 @@ App::patch('/v1/account/phone') $user ->setAttribute('phone', $phone) ->setAttribute('phoneVerification', false) // After this user needs to confirm phone number again -; + ; if (empty($passwordUpdate)) { $user @@ -2120,6 +2166,7 @@ App::patch('/v1/account/prefs') ->inject('dbForProject') ->inject('events') ->action(function (array $prefs, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $events) { + $user->setAttribute('prefs', $prefs); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); @@ -2150,6 +2197,7 @@ App::patch('/v1/account/status') ->inject('dbForProject') ->inject('events') ->action(function (?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Event $events) { + $user->setAttribute('status', false); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); @@ -2158,14 +2206,15 @@ App::patch('/v1/account/status') ->setParam('userId', $user->getId()) ->setPayload($response->output($user, Response::MODEL_ACCOUNT)); - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([])); } $protocol = $request->getProtocol(); $response - ->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')); + ->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); }); @@ -2194,6 +2243,7 @@ App::delete('/v1/account/sessions/:sessionId') ->inject('events') ->inject('project') ->action(function (?string $sessionId, ?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $events, Document $project) { + $protocol = $request->getProtocol(); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $sessionId = ($sessionId === 'current') @@ -2215,16 +2265,19 @@ App::delete('/v1/account/sessions/:sessionId') 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'))); + ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) + ; - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response - ->addHeader('X-Fallback-Cookies', \json_encode([])); + ->addHeader('X-Fallback-Cookies', \json_encode([])) + ; } $response - ->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')); + ->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->deleteCachedDocument('users', $user->getId()); @@ -2232,8 +2285,8 @@ App::delete('/v1/account/sessions/:sessionId') $events ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()) - ->setPayload($response->output($session, Response::MODEL_SESSION)); - + ->setPayload($response->output($session, Response::MODEL_SESSION)) + ; return $response->noContent(); } } @@ -2287,12 +2340,12 @@ App::patch('/v1/account/sessions/:sessionId') $provider = $session->getAttribute('provider'); $refreshToken = $session->getAttribute('providerRefreshToken'); - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; - $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); - if (! \class_exists($className)) { + if (!\class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } @@ -2303,7 +2356,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(''))); $dbForProject->updateDocument('sessions', $sessionId, $session); @@ -2316,7 +2369,8 @@ App::patch('/v1/account/sessions/:sessionId') $events ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()) - ->setPayload($response->output($session, Response::MODEL_SESSION)); + ->setPayload($response->output($session, Response::MODEL_SESSION)) + ; return $response->dynamic($session, Response::MODEL_SESSION); } @@ -2346,27 +2400,29 @@ App::delete('/v1/account/sessions') ->inject('locale') ->inject('events') ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $events) { + $protocol = $request->getProtocol(); $sessions = $user->getAttribute('sessions', []); foreach ($sessions as $session) {/** @var Document $session */ $dbForProject->deleteDocument('sessions', $session->getId()); - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([])); } $session ->setAttribute('current', false) - ->setAttribute('countryName', $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))); + ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) + ; if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { $session->setAttribute('current', true); $session->setAttribute('expire', DateTime::addSeconds(new \DateTime($session->getCreatedAt()), Auth::TOKEN_EXPIRATION_LOGIN_LONG)); - // If current session delete the cookies too + // If current session delete the cookies too $response - ->addCookie(Auth::$cookieName.'_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->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. @@ -2411,6 +2467,7 @@ App::post('/v1/account/recovery') ->inject('mails') ->inject('events') ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $mails, Event $events) { + if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -2425,7 +2482,7 @@ App::post('/v1/account/recovery') Query::equal('email', [$email]), ]); - if (! $profile) { + if (!$profile) { throw new Exception(Exception::USER_NOT_FOUND); } @@ -2466,12 +2523,12 @@ App::post('/v1/account/recovery') $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); - $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); - $subject = $locale->getText('emails.recovery.subject'); + $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); + $subject = $locale->getText("emails.recovery.subject"); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.recovery-'.$locale->default] ?? []; - if ($smtpEnabled && ! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.recovery-' . $locale->default] ?? []; + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message'] ?? $body; $subject = $customTemplate['subject'] ?? $subject; $from = $customTemplate['senderName'] ?? $from; @@ -2479,13 +2536,13 @@ App::post('/v1/account/recovery') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText('emails.recovery.hello')) + ->setParam('{{hello}}', $locale->getText("emails.recovery.hello")) ->setParam('{{name}}', $profile->getAttribute('name')) - ->setParam('{{body}}', $locale->getText('emails.recovery.body')) + ->setParam('{{body}}', $locale->getText("emails.recovery.body")) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText('emails.recovery.footer')) - ->setParam('{{thanks}}', $locale->getText('emails.recovery.thanks')) - ->setParam('{{signature}}', $locale->getText('emails.recovery.signature')) + ->setParam('{{footer}}', $locale->getText("emails.recovery.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.recovery.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.recovery.signature")) ->setParam('{{project}}', $projectName) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -2494,6 +2551,7 @@ App::post('/v1/account/recovery') $body = $body->render(); + $mails ->setRecipient($profile->getAttribute('email', '')) ->setName($profile->getAttribute('name')) @@ -2501,6 +2559,7 @@ App::post('/v1/account/recovery') ->setFrom($from) ->setSubject($subject) ->trigger(); + ; $events ->setParam('userId', $profile->getId()) @@ -2509,7 +2568,8 @@ App::post('/v1/account/recovery') ->setPayload($response->output( $recovery->setAttribute('secret', $secret), Response::MODEL_TOKEN - )); + )) + ; // Hide secret for clients $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); @@ -2559,7 +2619,7 @@ App::put('/v1/account/recovery') $tokens = $profile->getAttribute('tokens', []); $recovery = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_RECOVERY, $secret); - if (! $recovery) { + if (!$recovery) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -2571,7 +2631,7 @@ App::put('/v1/account/recovery') $history = $profile->getAttribute('passwordHistory', []); if ($historyLimit > 0) { $validator = new PasswordHistory($history, $profile->getAttribute('hash'), $profile->getAttribute('hashOptions')); - if (! $validator->isValid($password)) { + if (!$validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -2600,7 +2660,8 @@ App::put('/v1/account/recovery') $events ->setParam('userId', $profile->getId()) - ->setParam('tokenId', $recoveryDocument->getId()); + ->setParam('tokenId', $recoveryDocument->getId()) + ; $response->dynamic($recoveryDocument, Response::MODEL_TOKEN); }); @@ -2621,7 +2682,7 @@ App::post('/v1/account/verification') ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') - ->param('url', '', fn ($clients) => new Host($clients), '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, ['clients']) // TODO add built-in confirm page + ->param('url', '', fn($clients) => new Host($clients), '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, ['clients']) // TODO add built-in confirm page ->inject('request') ->inject('response') ->inject('project') @@ -2631,6 +2692,7 @@ App::post('/v1/account/verification') ->inject('events') ->inject('mails') ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $events, Mail $mails) { + if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -2669,12 +2731,12 @@ App::post('/v1/account/verification') $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); - $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); - $subject = $locale->getText('emails.verification.subject'); + $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); + $subject = $locale->getText("emails.verification.subject"); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.verification-'.$locale->default] ?? []; - if ($smtpEnabled && ! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? []; + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message'] ?? $body; $subject = $customTemplate['subject'] ?? $subject; $from = $customTemplate['senderName'] ?? $from; @@ -2682,13 +2744,13 @@ App::post('/v1/account/verification') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText('emails.verification.hello')) + ->setParam('{{hello}}', $locale->getText("emails.verification.hello")) ->setParam('{{name}}', $user->getAttribute('name')) - ->setParam('{{body}}', $locale->getText('emails.verification.body')) + ->setParam('{{body}}', $locale->getText("emails.verification.body")) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText('emails.verification.footer')) - ->setParam('{{thanks}}', $locale->getText('emails.verification.thanks')) - ->setParam('{{signature}}', $locale->getText('emails.verification.signature')) + ->setParam('{{footer}}', $locale->getText("emails.verification.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.verification.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.verification.signature")) ->setParam('{{project}}', $projectName) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -2703,7 +2765,8 @@ App::post('/v1/account/verification') ->setFrom($from) ->setRecipient($user->getAttribute('email')) ->setName($user->getAttribute('name') ?? '') - ->trigger(); + ->trigger() + ; $events ->setParam('userId', $user->getId()) @@ -2711,7 +2774,8 @@ App::post('/v1/account/verification') ->setPayload($response->output( $verification->setAttribute('secret', $verificationSecret), Response::MODEL_TOKEN - )); + )) + ; // Hide secret for clients $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); @@ -2744,7 +2808,8 @@ App::put('/v1/account/verification') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $events) { - $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + + $profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -2753,7 +2818,7 @@ App::put('/v1/account/verification') $tokens = $profile->getAttribute('tokens', []); $verification = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_VERIFICATION, $secret); - if (! $verification) { + if (!$verification) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -2774,7 +2839,8 @@ App::put('/v1/account/verification') $events ->setParam('userId', $userId) - ->setParam('tokenId', $verificationDocument->getId()); + ->setParam('tokenId', $verificationDocument->getId()) + ; $response->dynamic($verificationDocument, Response::MODEL_TOKEN); }); @@ -2804,6 +2870,7 @@ App::post('/v1/account/verification/phone') ->inject('project') ->inject('locale') ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $events, EventPhone $messaging, Document $project, Locale $locale) { + if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED); } @@ -2840,10 +2907,10 @@ App::post('/v1/account/verification/phone') $dbForProject->deleteCachedDocument('users', $user->getId()); - $message = Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl'); + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.verification-'.$locale->default] ?? []; - if (! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['sms.verification-' . $locale->default] ?? []; + if (!empty($customTemplate)) { $message = $customTemplate['message'] ?? $message; } @@ -2853,7 +2920,8 @@ App::post('/v1/account/verification/phone') $messaging ->setRecipient($user->getAttribute('phone')) ->setMessage($message) - ->trigger(); + ->trigger() + ; $events ->setParam('userId', $user->getId()) @@ -2861,7 +2929,8 @@ App::post('/v1/account/verification/phone') ->setPayload($response->output( $verification->setAttribute('secret', $secret), Response::MODEL_TOKEN - )); + )) + ; // Hide secret for clients $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); @@ -2894,7 +2963,8 @@ App::put('/v1/account/verification/phone') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $events) { - $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + + $profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -2902,7 +2972,7 @@ App::put('/v1/account/verification/phone') $verification = Auth::phoneTokenVerify($user->getAttribute('tokens', []), $secret); - if (! $verification) { + if (!$verification) { throw new Exception(Exception::USER_INVALID_TOKEN); } @@ -2922,7 +2992,8 @@ App::put('/v1/account/verification/phone') $events ->setParam('userId', $user->getId()) - ->setParam('tokenId', $verificationDocument->getId()); + ->setParam('tokenId', $verificationDocument->getId()) + ; $response->dynamic($verificationDocument, Response::MODEL_TOKEN); }); @@ -2961,7 +3032,7 @@ App::post('/v1/account/targets') $target = $dbForProject->getDocument('targets', $targetId); - if (! $target->isEmpty()) { + if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); } @@ -2969,7 +3040,7 @@ App::post('/v1/account/targets') '$id' => $targetId, // TO DO: what permissions should be given when created a target. '$permissions' => [ - Permission::read(Role::any()), + Permission::read(Role::any()) ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), @@ -3005,6 +3076,7 @@ App::patch('/v1/account/targets/:targetId/identifier') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -3049,6 +3121,7 @@ App::delete('/v1/account/targets/:targetId') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 047d99823e..0be2e0d849 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -1,6 +1,7 @@ output($output, $quality); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') ->setContentType('image/png') ->file($data); unset($image); @@ -82,12 +83,12 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro $accessTokenExpiry = $gitHubSession->getAttribute('providerAccessTokenExpiry'); $refreshToken = $gitHubSession->getAttribute('providerRefreshToken'); - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; - $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); - if (! \class_exists($className)) { + if (!\class_exists($className)) { throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED); } @@ -104,13 +105,13 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro $verificationId = $oauth2->getUserID($accessToken); if (empty($verificationId)) { - throw new \Exception('Locked tokens.'); // Race codition, handeled in catch + throw new \Exception("Locked tokens."); // Race codition, handeled in catch } $gitHubSession ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $oauth2->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); @@ -149,7 +150,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro return [ 'name' => $githubUser, - 'id' => $githubId, + 'id' => $githubId ]; } catch (Exception $error) { if ($logger) { @@ -176,7 +177,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('GitHub error log pushed with status code: '.$responseCode); + Console::info('GitHub error log pushed with status code: ' . $responseCode); } Console::warning("Failed: {$error->getMessage()}"); @@ -201,12 +202,12 @@ App::get('/v1/avatars/credit-cards/:code') ->label('sdk.description', '/docs/references/avatars/get-credit-card.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) - ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.') + ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true) ->inject('response') - ->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('credit-cards', $code, $width, $height, $quality, $response)); + ->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('credit-cards', $code, $width, $height, $quality, $response)); App::get('/v1/avatars/browsers/:code') ->desc('Get Browser Icon') @@ -266,17 +267,18 @@ App::get('/v1/avatars/image') ->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.', true) ->inject('response') ->action(function (string $url, int $width, int $height, Response $response) { + $quality = 80; $output = 'png'; $type = 'png'; - if (! \extension_loaded('imagick')) { + if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } $fetch = @\file_get_contents($url, false); - if (! $fetch) { + if (!$fetch) { throw new Exception(Exception::AVATAR_IMAGE_NOT_FOUND); } @@ -291,7 +293,7 @@ App::get('/v1/avatars/image') $data = $image->output($output, $quality); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') ->setContentType('image/png') ->file($data); unset($image); @@ -313,13 +315,14 @@ App::get('/v1/avatars/favicon') ->param('url', '', new URL(['http', 'https']), 'Website URL which you want to fetch the favicon from.') ->inject('response') ->action(function (string $url, Response $response) { + $width = 56; $height = 56; $quality = 80; $output = 'png'; $type = 'png'; - if (! \extension_loaded('imagick')) { + if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } @@ -341,7 +344,7 @@ App::get('/v1/avatars/favicon') \curl_close($curl); - if (! $html) { + if (!$html) { throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); } @@ -392,7 +395,7 @@ App::get('/v1/avatars/favicon') if (empty($outputHref) || empty($outputExt)) { $default = \parse_url($url); - $outputHref = $default['scheme'].'://'.$default['host'].'/favicon.ico'; + $outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico'; $outputExt = 'ico'; } @@ -403,14 +406,14 @@ App::get('/v1/avatars/favicon') throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found'); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') ->setContentType('image/x-icon') ->file($data); } $fetch = @\file_get_contents($outputHref, false); - if (! $fetch) { + if (!$fetch) { throw new Exception(Exception::AVATAR_ICON_NOT_FOUND); } @@ -420,7 +423,7 @@ App::get('/v1/avatars/favicon') $data = $image->output($output, $quality); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') ->setContentType('image/png') ->file($data); unset($image); @@ -443,6 +446,7 @@ App::get('/v1/avatars/qr') ->param('download', false, new Boolean(true), 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true) ->inject('response') ->action(function (string $text, int $size, int $margin, bool $download, Response $response) { + $download = ($download === '1' || $download === 'true' || $download === 1 || $download === true); $options = new QROptions([ 'addQuietzone' => true, @@ -460,7 +464,7 @@ App::get('/v1/avatars/qr') $image->crop((int) $size, (int) $size); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') ->send($image->output('png', 9)); }); @@ -484,16 +488,17 @@ App::get('/v1/avatars/initials') ->inject('response') ->inject('user') ->action(function (string $name, int $width, int $height, string $background, Response $response, Document $user) { + $themes = [ ['background' => '#FFA1CE'], // Default (Pink) ['background' => '#FDC584'], // Orange ['background' => '#94DBD1'], // Green ['background' => '#A1C4FF'], // Blue ['background' => '#FFA1CE'], // Pink - ['background' => '#CBB1FC'], // Purple + ['background' => '#CBB1FC'] // Purple ]; - $name = (! empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', '')); + $name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', '')); $words = \explode(' ', \strtoupper($name)); // if there is no space, try to split by `_` underscore $words = (count($words) == 1) ? \explode('_', \strtoupper($name)) : $words; @@ -515,7 +520,7 @@ App::get('/v1/avatars/initials') // Wrap rand value to avoid out of range $rand = ($rand > \count($themes) - 1) ? $rand % \count($themes) : $rand; - $background = (! empty($background)) ? '#'.$background : $themes[$rand]['background']; + $background = (!empty($background)) ? '#' . $background : $themes[$rand]['background']; $image = new \Imagick(); $punch = new \Imagick(); @@ -524,8 +529,8 @@ App::get('/v1/avatars/initials') $punch->newImage($width, $height, 'transparent'); - $draw->setFont(__DIR__.'/../../assets/fonts/poppins-v9-latin-500.ttf'); - $image->setFont(__DIR__.'/../../assets/fonts/poppins-v9-latin-500.ttf'); + $draw->setFont(__DIR__ . "/../../assets/fonts/poppins-v9-latin-500.ttf"); + $image->setFont(__DIR__ . "/../../assets/fonts/poppins-v9-latin-500.ttf"); $draw->setFillColor(new ImagickPixel('black')); $draw->setFontSize($fontSize); @@ -537,13 +542,13 @@ App::get('/v1/avatars/initials') $punch->negateImage(true, Imagick::CHANNEL_ALPHA); $image->newImage($width, $height, $background); - $image->setImageFormat('png'); + $image->setImageFormat("png"); $image->compositeImage($punch, Imagick::COMPOSITE_COPYOPACITY, 0, 0); //$image->setImageCompressionQuality(9 - round(($quality / 100) * 9)); $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') ->file($image->getImageBlob()); }); @@ -577,7 +582,7 @@ App::get('/v1/cards/cloud') throw new Exception(Exception::USER_NOT_FOUND); } - if (! $mock) { + if (!$mock) { $name = $user->getAttribute('name', 'Anonymous'); $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); @@ -597,9 +602,9 @@ App::get('/v1/cards/cloud') $createdAt = new \DateTime($employees[$email]['memberSince'] ?? ''); } - if (! $isEmployee && ! empty($githubName)) { + if (!$isEmployee && !empty($githubName)) { $employeeGitHub = \array_search(\strtolower($githubName), \array_map(fn ($employee) => \strtolower($employee['gitHub']) ?? '', $employees)); - if (! empty($employeeGitHub)) { + if (!empty($employeeGitHub)) { $isEmployee = true; $employeeNumber = $isEmployee ? $employees[$employeeGitHub]['spot'] : ''; $createdAt = new \DateTime($employees[$employeeGitHub]['memberSince'] ?? ''); @@ -640,20 +645,20 @@ App::get('/v1/cards/cloud') $isGolden = $isEmployee || $isHero || $isContributor; $isPlatinum = $isGolden ? false : $isPlatinum; - $memberSince = \strtoupper('Member since '.$createdAt->format('M').' '.$createdAt->format('d').', '.$createdAt->format('o')); + $memberSince = \strtoupper('Member since ' . $createdAt->format('M') . ' ' . $createdAt->format('d') . ', ' . $createdAt->format('o')); $imagePath = $isGolden ? 'front-golden.png' : ($isPlatinum ? 'front-platinum.png' : 'front.png'); - $baseImage = new \Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$imagePath); + $baseImage = new \Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $imagePath); if ($isEmployee) { - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/employee.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/employee.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 793, 35); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); $text->setFillColor(new \ImagickPixel('#FFFADF')); $text->setFontSize(\strlen($employeeNumber) <= 2 ? 54 : 48); $text->setFontWeight(700); @@ -661,7 +666,7 @@ App::get('/v1/cards/cloud') $hashtag = new \ImagickDraw(); $hashtag->setTextAlignment(Imagick::ALIGN_CENTER); - $hashtag->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); + $hashtag->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); $hashtag->setFillColor(new \ImagickPixel('#FFFADF')); $hashtag->setFontSize(28); $hashtag->setFontWeight(700); @@ -684,25 +689,25 @@ App::get('/v1/cards/cloud') } if ($isContributor) { - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/contributor.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/contributor.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 793, 34); } if ($isHero) { - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/hero.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/hero.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 793, 34); } - setlocale(LC_ALL, 'en_US.utf8'); + setlocale(LC_ALL, "en_US.utf8"); // $name = \iconv("utf-8", "ascii//TRANSLIT", $name); // $memberSince = \iconv("utf-8", "ascii//TRANSLIT", $memberSince); // $githubName = \iconv("utf-8", "ascii//TRANSLIT", $githubName); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__.'/../../../public/fonts/Poppins-Bold.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/Poppins-Bold.ttf'); $text->setFillColor(new \ImagickPixel('#FFFFFF')); if (\strlen($name) > 32) { @@ -721,17 +726,17 @@ App::get('/v1/cards/cloud') $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__.'/../../../public/fonts/Inter-SemiBold.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/Inter-SemiBold.ttf'); $text->setFillColor(new \ImagickPixel($isGolden || $isPlatinum ? '#FFFFFF' : '#FFB9CC')); $text->setFontSize(27); $text->setFontWeight(600); $text->setTextKerning(1.08); $baseImage->annotateImage($text, 512, 541, 0, \strtoupper($memberSince)); - if (! empty($githubName)) { + if (!empty($githubName)) { $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__.'/../../../public/fonts/Inter-Regular.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Regular.ttf'); $text->setFillColor(new \ImagickPixel('#FFFFFF')); $text->setFontSize($scalingDown ? 28 : 32); $text->setFontWeight(400); @@ -739,18 +744,18 @@ App::get('/v1/cards/cloud') $baseImage->annotateImage($text, 512 + 20 + 4, 373 + ($scalingDown ? 2 : 0), 0, $githubName); - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $precisionFix = 5; $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 512 - ($metrics['textWidth'] / 2) - 20 - 4, 373 - ($metrics['textHeight'] - $precisionFix)); } - if (! empty($width) || ! empty($height)) { + if (!empty($width) || !empty($height)) { $baseImage->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') ->file($baseImage->getImageBlob()); }); @@ -784,7 +789,7 @@ App::get('/v1/cards/cloud-back') throw new Exception(Exception::USER_NOT_FOUND); } - if (! $mock) { + if (!$mock) { $userId = $user->getId(); $email = $user->getAttribute('email', ''); @@ -804,31 +809,31 @@ App::get('/v1/cards/cloud-back') $isPlatinum = $mock === 'platinum'; } - $userId = 'UID '.$userId; + $userId = 'UID ' . $userId; $isPlatinum = $isGolden ? false : $isPlatinum; $imagePath = $isGolden ? 'back-golden.png' : ($isPlatinum ? 'back-platinum.png' : 'back.png'); - $baseImage = new \Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$imagePath); + $baseImage = new \Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $imagePath); - setlocale(LC_ALL, 'en_US.utf8'); + setlocale(LC_ALL, "en_US.utf8"); // $userId = \iconv("utf-8", "ascii//TRANSLIT", $userId); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_CENTER); - $text->setFont(__DIR__.'/../../../public/fonts/SourceCodePro-Regular.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/SourceCodePro-Regular.ttf'); $text->setFillColor(new \ImagickPixel($isGolden ? '#664A1E' : ($isPlatinum ? '#555555' : '#E8E9F0'))); $text->setFontSize(28); $text->setFontWeight(400); $baseImage->annotateImage($text, 512, 596, 0, $userId); - if (! empty($width) || ! empty($height)) { + if (!empty($width) || !empty($height)) { $baseImage->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') ->file($baseImage->getImageBlob()); }); @@ -862,7 +867,7 @@ App::get('/v1/cards/cloud-og') throw new Exception(Exception::USER_NOT_FOUND); } - if (! $mock) { + if (!$mock) { $internalId = $user->getInternalId(); $bgVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); $cardVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); @@ -886,9 +891,9 @@ App::get('/v1/cards/cloud-og') $createdAt = new \DateTime($employees[$email]['memberSince'] ?? ''); } - if (! $isEmployee && ! empty($githubName)) { + if (!$isEmployee && !empty($githubName)) { $employeeGitHub = \array_search(\strtolower($githubName), \array_map(fn ($employee) => \strtolower($employee['gitHub']) ?? '', $employees)); - if (! empty($employeeGitHub)) { + if (!empty($employeeGitHub)) { $isEmployee = true; $employeeNumber = $isEmployee ? $employees[$employeeGitHub]['spot'] : ''; $createdAt = new \DateTime($employees[$employeeGitHub]['memberSince'] ?? ''); @@ -935,17 +940,17 @@ App::get('/v1/cards/cloud-og') $isGolden = $isEmployee || $isHero || $isContributor; $isPlatinum = $isGolden ? false : $isPlatinum; - $memberSince = \strtoupper('Member since '.$createdAt->format('M').' '.$createdAt->format('d').', '.$createdAt->format('o')); + $memberSince = \strtoupper('Member since ' . $createdAt->format('M') . ' ' . $createdAt->format('d') . ', ' . $createdAt->format('o')); - $baseImage = new \Imagick(__DIR__."/../../../public/images/cards/cloud/og-background{$bgVariation}.png"); + $baseImage = new \Imagick(__DIR__ . "/../../../public/images/cards/cloud/og-background{$bgVariation}.png"); $cardType = $isGolden ? '-golden' : ($isPlatinum ? '-platinum' : ''); - $image = new Imagick(__DIR__."/../../../public/images/cards/cloud/og-card{$cardType}{$cardVariation}.png"); + $image = new Imagick(__DIR__ . "/../../../public/images/cards/cloud/og-card{$cardType}{$cardVariation}.png"); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 1008 / 2 - $image->getImageWidth() / 2, 1008 / 2 - $image->getImageHeight() / 2); - $imageLogo = new Imagick(__DIR__.'/../../../public/images/cards/cloud/og-background-logo.png'); - $imageShadow = new Imagick(__DIR__."/../../../public/images/cards/cloud/og-shadow{$cardType}.png"); + $imageLogo = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/og-background-logo.png'); + $imageShadow = new Imagick(__DIR__ . "/../../../public/images/cards/cloud/og-shadow{$cardType}.png"); if ($cardVariation === '1') { $baseImage->compositeImage($imageLogo, Imagick::COMPOSITE_OVER, 32, 1008 - $imageLogo->getImageHeight() - 32); $baseImage->compositeImage($imageShadow, Imagick::COMPOSITE_OVER, -450, 700); @@ -959,19 +964,19 @@ App::get('/v1/cards/cloud-og') if ($isEmployee) { $file = $cardVariation === '3' ? 'employee-skew.png' : 'employee.png'; - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$file); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $file); $image->setGravity(Imagick::GRAVITY_CENTER); $hashtag = new \ImagickDraw(); $hashtag->setTextAlignment(Imagick::ALIGN_LEFT); - $hashtag->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); + $hashtag->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); $hashtag->setFillColor(new \ImagickPixel('#FFFADF')); $hashtag->setFontSize(20); $hashtag->setFontWeight(700); $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_LEFT); - $text->setFont(__DIR__.'/../../../public/fonts/Inter-Bold.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Bold.ttf'); $text->setFillColor(new \ImagickPixel('#FFFADF')); $text->setFontSize(\strlen($employeeNumber) <= 1 ? 36 : 28); $text->setFontWeight(700); @@ -1045,7 +1050,7 @@ App::get('/v1/cards/cloud-og') if ($isContributor) { $file = $cardVariation === '3' ? 'contributor-skew.png' : 'contributor.png'; - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$file); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $file); $image->setGravity(Imagick::GRAVITY_CENTER); if ($cardVariation === '1') { @@ -1063,7 +1068,7 @@ App::get('/v1/cards/cloud-og') if ($isHero) { $file = $cardVariation === '3' ? 'hero-skew.png' : 'hero.png'; - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/'.$file); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/' . $file); $image->setGravity(Imagick::GRAVITY_CENTER); if ($cardVariation === '1') { @@ -1079,14 +1084,14 @@ App::get('/v1/cards/cloud-og') } } - setlocale(LC_ALL, 'en_US.utf8'); + setlocale(LC_ALL, "en_US.utf8"); // $name = \iconv("utf-8", "ascii//TRANSLIT", $name); // $memberSince = \iconv("utf-8", "ascii//TRANSLIT", $memberSince); // $githubName = \iconv("utf-8", "ascii//TRANSLIT", $githubName); $textName = new \ImagickDraw(); $textName->setTextAlignment(Imagick::ALIGN_CENTER); - $textName->setFont(__DIR__.'/../../../public/fonts/Poppins-Bold.ttf'); + $textName->setFont(__DIR__ . '/../../../public/fonts/Poppins-Bold.ttf'); $textName->setFillColor(new \ImagickPixel('#FFFFFF')); if (\strlen($name) > 32) { @@ -1123,7 +1128,7 @@ App::get('/v1/cards/cloud-og') $textMember = new \ImagickDraw(); $textMember->setTextAlignment(Imagick::ALIGN_CENTER); - $textMember->setFont(__DIR__.'/../../../public/fonts/Inter-Medium.ttf'); + $textMember->setFont(__DIR__ . '/../../../public/fonts/Inter-Medium.ttf'); $textMember->setFillColor(new \ImagickPixel($isGolden || $isPlatinum ? '#FFFFFF' : '#FFB9CC')); $textMember->setFontWeight(500); $textMember->setTextKerning(1.12); @@ -1153,10 +1158,10 @@ App::get('/v1/cards/cloud-og') $baseImage->drawImage($textMember); } - if (! empty($githubName)) { + if (!empty($githubName)) { $text = new \ImagickDraw(); $text->setTextAlignment(Imagick::ALIGN_LEFT); - $text->setFont(__DIR__.'/../../../public/fonts/Inter-Regular.ttf'); + $text->setFont(__DIR__ . '/../../../public/fonts/Inter-Regular.ttf'); $text->setFillColor(new \ImagickPixel('#FFFFFF')); $text->setFontSize($scalingDown ? 16 : 20); $text->setFontWeight(400); @@ -1167,7 +1172,7 @@ App::get('/v1/cards/cloud-og') $group = new Imagick(); $groupWidth = $metrics['textWidth'] + 32 + 4; $group->newImage($groupWidth, $metrics['textHeight'] + 10, '#00000000'); - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $image->resizeImage(32, 32, Imagick::FILTER_LANCZOS, 1); $precisionFix = -1; @@ -1185,7 +1190,7 @@ App::get('/v1/cards/cloud-og') $group = new Imagick(); $groupWidth = $metrics['textWidth'] + 32 + 4; $group->newImage($groupWidth, $metrics['textHeight'] + 10, '#00000000'); - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $image->resizeImage(32, 32, Imagick::FILTER_LANCZOS, 1); $precisionFix = -1; @@ -1205,7 +1210,7 @@ App::get('/v1/cards/cloud-og') $text->annotation(320 + 15 + 2, 640, $githubName); $metrics = $baseImage->queryFontMetrics($text, $githubName); - $image = new Imagick(__DIR__.'/../../../public/images/cards/cloud/github-skew.png'); + $image = new Imagick(__DIR__ . '/../../../public/images/cards/cloud/github-skew.png'); $image->setGravity(Imagick::GRAVITY_CENTER); $baseImage->compositeImage($image, Imagick::COMPOSITE_OVER, 512 - ($metrics['textWidth'] / 2), 518 + \strlen($githubName) * 1.3); @@ -1213,12 +1218,12 @@ App::get('/v1/cards/cloud-og') } } - if (! empty($width) || ! empty($height)) { + if (!empty($width) || !empty($height)) { $baseImage->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1); } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->setContentType('image/png') ->file($baseImage->getImageBlob()); }); diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 846964cad6..f2ea83af58 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -15,6 +15,7 @@ App::init() } }); + App::get('/v1/console/variables') ->desc('Get Variables') ->groups(['api', 'projects']) @@ -28,6 +29,7 @@ App::get('/v1/console/variables') ->label('sdk.response.model', Response::MODEL_CONSOLE_VARIABLES) ->inject('response') ->action(function (Response $response) { + $variables = new Document([ '_APP_DOMAIN_TARGET' => App::getEnv('_APP_DOMAIN_TARGET'), '_APP_STORAGE_LIMIT' => +App::getEnv('_APP_STORAGE_LIMIT'), @@ -38,6 +40,7 @@ App::get('/v1/console/variables') $response->dynamic($variables, Response::MODEL_CONSOLE_VARIABLES); }); + App::post('/v1/console/assistant') ->desc('Ask Query') ->groups(['api', 'assistant']) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 8f1868f17e..aa7999b844 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -17,7 +17,9 @@ use MaxMind\Db\Reader; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; +use Utopia\Database\Adapter\MariaDB; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate as DuplicateException; @@ -44,8 +46,8 @@ use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; -use Utopia\Validator\Integer; use Utopia\Validator\IP; +use Utopia\Validator\Integer; use Utopia\Validator\JSON; use Utopia\Validator\Nullable; use Utopia\Validator\Range; @@ -58,7 +60,6 @@ use Utopia\Validator\WhiteList; * * * @return Document Newly created attribute document - * * @throws Exception */ function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $database, Event $events): Document @@ -81,14 +82,14 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (! empty($format)) { - if (! Structure::hasFormat($format, $type)) { + if (!empty($format)) { + if (!Structure::hasFormat($format, $type)) { throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} attributes."); } } @@ -104,7 +105,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_'.$db->getInternalId(), $options['relatedCollection'] ?? ''); + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related collection was not found.'); } @@ -112,7 +113,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $attribute = new Document([ - '$id' => ID::custom($db->getInternalId().'_'.$collection->getInternalId().'_'.$key), + '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), 'key' => $key, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), @@ -138,13 +139,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); } catch (\Exception $e) { - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); throw $e; } - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -154,7 +155,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$twoWayKey), + '$id' => ID::custom($db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), 'key' => $twoWayKey, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), @@ -182,13 +183,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); } catch (\Exception $e) { - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$relatedCollection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); throw $e; } - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$relatedCollection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } $database @@ -230,13 +231,13 @@ function updateAttribute( throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key); + $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -262,7 +263,7 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); } - $collectionId = 'database_'.$db->getInternalId().'_collection_'.$collection->getInternalId(); + $collectionId = 'database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId(); $attribute ->setAttribute('default', $default) @@ -286,18 +287,18 @@ function updateAttribute( } else { $validator = new Range($min, $max, Database::VAR_FLOAT); - if (! is_null($default)) { + if (!is_null($default)) { $default = \floatval($default); } } - if (! is_null($default) && ! $validator->isValid($default)) { + if (!is_null($default) && !$validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } $options = [ 'min' => $min, - 'max' => $max, + 'max' => $max ]; $attribute->setAttribute('formatOptions', $options); @@ -313,12 +314,12 @@ function updateAttribute( } } - if (! is_null($default) && ! in_array($default, $elements)) { + if (!is_null($default) && !in_array($default, $elements)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); } $options = [ - 'elements' => $elements, + 'elements' => $elements ]; $attribute->setAttribute('formatOptions', $options); @@ -337,13 +338,13 @@ function updateAttribute( ); if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_'.$db->getInternalId(), $primaryDocumentOptions['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$primaryDocumentOptions['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $relatedCollection->getId()); + $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); } } else { $dbForProject->updateAttribute( @@ -355,8 +356,8 @@ function updateAttribute( ); } - $dbForProject->updateDocument('attributes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key, $attribute); - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collection->getId()); + $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collection->getId()); $events ->setContext('collection', $collection) @@ -389,6 +390,7 @@ App::post('/v1/databases') ->inject('dbForProject') ->inject('events') ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $events) { + $databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId; try { @@ -418,7 +420,7 @@ App::post('/v1/databases') 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '', + 'format' => $attribute['format'] ?? '' ]); } @@ -431,7 +433,7 @@ App::post('/v1/databases') 'orders' => $index['orders'], ]); } - $dbForProject->createCollection('database_'.$database->getInternalId(), $attributes, $indexes); + $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); } @@ -454,14 +456,15 @@ App::get('/v1/databases') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DATABASE_LIST) - ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -502,6 +505,7 @@ App::get('/v1/databases/:databaseId') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, Response $response, Database $dbForProject) { + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -529,6 +533,7 @@ App::get('/v1/databases/:databaseId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -541,13 +546,13 @@ App::get('/v1/databases/:databaseId/logs') $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'database/'.$databaseId; + $resource = 'database/' . $databaseId; $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -575,14 +580,14 @@ App::get('/v1/databases/:databaseId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -595,6 +600,7 @@ App::get('/v1/databases/:databaseId/logs') ]), Response::MODEL_LOG_LIST); }); + App::put('/v1/databases/:databaseId') ->desc('Update Database') ->groups(['api', 'database', 'schema']) @@ -616,6 +622,7 @@ App::put('/v1/databases/:databaseId') ->inject('dbForProject') ->inject('events') ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $events) { + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -630,7 +637,7 @@ App::put('/v1/databases/:databaseId') } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. '.$exception->getMessage()); + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage()); } $events->setParam('databaseId', $database->getId()); @@ -657,18 +664,19 @@ App::delete('/v1/databases/:databaseId') ->inject('events') ->inject('deletes') ->action(function (string $databaseId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - if (! $dbForProject->deleteDocument('databases', $databaseId)) { + if (!$dbForProject->deleteDocument('databases', $databaseId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } $dbForProject->deleteCachedDocument('databases', $database->getId()); - $dbForProject->deleteCachedCollection('databases_'.$database->getInternalId()); + $dbForProject->deleteCachedCollection('databases_' . $database->getInternalId()); $deletes ->setType(DELETE_TYPE_DOCUMENT) @@ -707,9 +715,10 @@ App::post('/v1/databases/:databaseId/collections') ->inject('mode') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $events) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } @@ -719,7 +728,7 @@ App::post('/v1/databases/:databaseId/collections') $permissions = Permission::aggregate($permissions); try { - $dbForProject->createDocument('database_'.$database->getInternalId(), new Document([ + $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ '$id' => $collectionId, 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $databaseId, @@ -729,9 +738,9 @@ App::post('/v1/databases/:databaseId/collections') 'name' => $name, 'search' => implode(' ', [$collectionId, $name]), ])); - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->createCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), permissions: $permissions ?? [], documentSecurity: $documentSecurity); + $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions ?? [], documentSecurity: $documentSecurity); } catch (DuplicateException) { throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); } catch (LimitException) { @@ -761,21 +770,22 @@ App::get('/v1/databases/:databaseId/collections') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_COLLECTION_LIST) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' queries are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long. You may filter on the following attributes: '.implode(', ', Collections::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new 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) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -785,7 +795,7 @@ App::get('/v1/databases/:databaseId/collections') if ($cursor) { /** @var Query $cursor */ $collectionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); @@ -797,8 +807,8 @@ App::get('/v1/databases/:databaseId/collections') $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ - 'collections' => $dbForProject->find('database_'.$database->getInternalId(), $queries), - 'total' => $dbForProject->count('database_'.$database->getInternalId(), $filterQueries, APP_LIMIT_COUNT), + 'collections' => $dbForProject->find('database_' . $database->getInternalId(), $queries), + 'total' => $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_COLLECTION_LIST); }); @@ -820,13 +830,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -855,13 +866,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_'.$database->getInternalId().'_collection_'.$collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -873,13 +885,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'database/'.$databaseId.'/collection/'.$collectionId; + $resource = 'database/' . $databaseId . '/collection/' . $collectionId; $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -907,14 +919,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -927,6 +939,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ]), Response::MODEL_LOG_LIST); }); + App::put('/v1/databases/:databaseId/collections/:collectionId') ->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default']) ->desc('Update Collection') @@ -953,13 +966,14 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->inject('mode') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $events) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -973,17 +987,17 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') $enabled ??= $collection->getAttribute('enabled', true); try { - $collection = $dbForProject->updateDocument('database_'.$database->getInternalId(), $collectionId, $collection + $collection = $dbForProject->updateDocument('database_' . $database->getInternalId(), $collectionId, $collection ->setAttribute('name', $name) ->setAttribute('$permissions', $permissions) ->setAttribute('documentSecurity', $documentSecurity) ->setAttribute('enabled', $enabled) ->setAttribute('search', implode(' ', [$collectionId, $name]))); - $dbForProject->updateCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. '.$exception->getMessage()); + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage()); } $events @@ -1016,23 +1030,24 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') ->inject('events') ->inject('deletes') ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode, Event $events, Delete $deletes) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (! $dbForProject->deleteDocument('database_'.$database->getInternalId(), $collectionId)) { + if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->deleteCachedCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId()); + $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); $deletes ->setType(DELETE_TYPE_DOCUMENT) @@ -1075,9 +1090,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + // Ensure attribute default is within required size $validator = new Text($size, 0); - if (! is_null($default) && ! $validator->isValid($default)) { + if (!is_null($default) && !$validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1128,6 +1144,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, @@ -1161,7 +1178,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->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('key', '', new Key(), 'Attribute Key.') - ->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE, min: 0), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' elements are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long.') + ->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE, min: 0), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.') ->param('required', null, new Boolean(), 'Is attribute required?') ->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) ->param('array', false, new Boolean(), 'Is attribute an array?', true) @@ -1170,6 +1187,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + // use length of longest string as attribute size $size = 0; foreach ($elements as $element) { @@ -1180,7 +1198,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') $size = ($length > $size) ? $length : $size; } - if (! is_null($default) && ! in_array($default, $elements)) { + if (!is_null($default) && !in_array($default, $elements)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); } @@ -1226,6 +1244,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, @@ -1267,6 +1286,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, @@ -1310,6 +1330,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + // Ensure attribute default is within range $min = (is_null($min)) ? PHP_INT_MIN : \intval($min); $max = (is_null($max)) ? PHP_INT_MAX : \intval($max); @@ -1320,7 +1341,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege $validator = new Range($min, $max, Database::VAR_INTEGER); - if (! is_null($default) && ! $validator->isValid($default)) { + if (!is_null($default) && !$validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1342,7 +1363,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege $formatOptions = $attribute->getAttribute('formatOptions', []); - if (! empty($formatOptions)) { + if (!empty($formatOptions)) { $attribute->setAttribute('min', \intval($formatOptions['min'])); $attribute->setAttribute('max', \intval($formatOptions['max'])); } @@ -1380,6 +1401,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + // Ensure attribute default is within range $min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min); $max = (is_null($max)) ? PHP_FLOAT_MAX : \floatval($max); @@ -1389,13 +1411,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' } // Ensure default value is a float - if (! is_null($default)) { + if (!is_null($default)) { $default = \floatval($default); } $validator = new Range($min, $max, Database::VAR_FLOAT); - if (! is_null($default) && ! $validator->isValid($default)) { + if (!is_null($default) && !$validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1415,7 +1437,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' $formatOptions = $attribute->getAttribute('formatOptions', []); - if (! empty($formatOptions)) { + if (!empty($formatOptions)) { $attribute->setAttribute('min', \floatval($formatOptions['min'])); $attribute->setAttribute('max', \floatval($formatOptions['max'])); } @@ -1451,6 +1473,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_BOOLEAN, @@ -1491,6 +1514,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { + $filters[] = 'datetime'; $attribute = createAttribute($databaseId, $collectionId, new Document([ @@ -1569,7 +1593,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati 'twoWay' => $twoWay, 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, - ], + ] ]), $response, $dbForProject, @@ -1602,17 +1626,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' queries are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long. You may filter on the following attributes: '.implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1628,7 +1653,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') if ($cursor) { $attributeId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('attributes', [ + $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [ Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$attributeId]), @@ -1669,26 +1694,27 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') Response::MODEL_ATTRIBUTE_IP, Response::MODEL_ATTRIBUTE_DATETIME, Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING, ])// needs to be last, since its condition would dominate any other string attribute + Response::MODEL_ATTRIBUTE_STRING])// needs to be last, since its condition would dominate any other string attribute ->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('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId().'_'.$collection->getInternalId().'_'.$key); + $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -1744,6 +1770,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin ->inject('dbForProject') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $events) { + $attribute = updateAttribute( databaseId: $databaseId, collectionId: $collectionId, @@ -1815,7 +1842,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/ ->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('key', '', new Key(), 'Attribute Key.') - ->param('elements', null, new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' elements are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long.') + ->param('elements', null, new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.') ->param('required', null, new Boolean(), 'Is attribute required?') ->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.') ->inject('response') @@ -1957,7 +1984,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ $formatOptions = $attribute->getAttribute('formatOptions', []); - if (! empty($formatOptions)) { + if (!empty($formatOptions)) { $attribute->setAttribute('min', \intval($formatOptions['min'])); $attribute->setAttribute('max', \intval($formatOptions['max'])); } @@ -2006,7 +2033,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float $formatOptions = $attribute->getAttribute('formatOptions', []); - if (! empty($formatOptions)) { + if (!empty($formatOptions)) { $attribute->setAttribute('min', \floatval($formatOptions['min'])); $attribute->setAttribute('max', \floatval($formatOptions['max'])); } @@ -2130,7 +2157,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ type: Database::VAR_RELATIONSHIP, required: false, options: [ - 'onDelete' => $onDelete, + 'onDelete' => $onDelete ] ); @@ -2167,18 +2194,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $db = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key); + $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2189,19 +2217,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_'.$db->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); if ($relatedAttribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2211,8 +2239,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $options['relatedCollection']); - $dbForProject->deleteCachedCollection('database_'.$db->getInternalId().'_collection_'.$relatedCollection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } @@ -2272,20 +2300,21 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->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('key', null, new Key(), 'Index Key.') ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL, Database::INDEX_ARRAY]), 'Index type.') - ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' attributes are allowed, each 32 characters long.') - ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' orders are allowed.', true) + ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.') + ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) ->inject('response') ->inject('dbForProject') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $db = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2293,7 +2322,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $count = $dbForProject->count('indexes', [ Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$db->getInternalId()]), + Query::equal('databaseInternalId', [$db->getInternalId()]) ], 61); $limit = $dbForProject->getLimitForIndexes(); @@ -2303,7 +2332,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } // Convert Document[] to array of attribute metadata - $oldAttributes = \array_map(fn ($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); + $oldAttributes = \array_map(fn($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); $oldAttributes[] = [ 'key' => '$id', @@ -2312,7 +2341,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'required' => true, 'array' => false, 'default' => null, - 'size' => 36, + 'size' => 36 ]; $oldAttributes[] = [ @@ -2323,7 +2352,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'required' => false, 'array' => false, 'default' => null, - 'size' => 0, + 'size' => 0 ]; $oldAttributes[] = [ @@ -2334,7 +2363,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'required' => false, 'array' => false, 'default' => null, - 'size' => 0, + 'size' => 0 ]; // lengths hidden by default @@ -2345,7 +2374,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key')); if ($attributeIndex === false) { - throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: '.$attribute); + throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: ' . $attribute); } $attributeStatus = $oldAttributes[$attributeIndex]['status']; @@ -2353,12 +2382,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $attributeSize = $oldAttributes[$attributeIndex]['size']; if ($attributeType === Database::VAR_RELATIONSHIP) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship attribute: '.$oldAttributes[$attributeIndex]['key']); + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship attribute: ' . $oldAttributes[$attributeIndex]['key']); } // ensure attribute is available if ($attributeStatus !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: '.$oldAttributes[$attributeIndex]['key']); + throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']); } // set attribute size as index length only for strings @@ -2366,7 +2395,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } $index = new Document([ - '$id' => ID::custom($db->getInternalId().'_'.$collection->getInternalId().'_'.$key), + '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck 'databaseInternalId' => $db->getInternalId(), @@ -2380,7 +2409,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ]); $validator = new IndexValidator($dbForProject->getAdapter()->getMaxIndexLength()); - if (! $validator->isValid($collection->setAttribute('indexes', $index, Document::SET_TYPE_APPEND))) { + if (!$validator->isValid($collection->setAttribute('indexes', $index, Document::SET_TYPE_APPEND))) { throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); } @@ -2390,7 +2419,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); $database ->setType(DATABASE_TYPE_CREATE_INDEX) @@ -2424,17 +2453,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->label('sdk.response.model', Response::MODEL_INDEX_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' queries are allowed, each '.APP_LIMIT_ARRAY_ELEMENT_SIZE.' characters long. You may filter on the following attributes: '.implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2443,17 +2473,17 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $queries = Query::parseQueries($queries); \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); - $cursor = reset($cursor); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); if ($cursor) { $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = Authorization::skip(fn() => $dbForProject->find('indexes', [ Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$indexId]), - Query::limit(1), + Query::limit(1) ])); if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { @@ -2488,12 +2518,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2507,6 +2538,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $response->dynamic($index, Response::MODEL_INDEX); }); + App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->alias('/v1/database/collections/:collectionId/indexes/:key', ['databaseId' => 'default']) ->desc('Delete Index') @@ -2529,18 +2561,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->inject('database') ->inject('events') ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $db = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $db->getInternalId().'_'.$collection->getInternalId().'_'.$key); + $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if (empty($index->getId())) { throw new Exception(Exception::INDEX_NOT_FOUND); @@ -2551,7 +2584,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_'.$db->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); $database ->setType(DATABASE_TYPE_DELETE_INDEX) @@ -2601,6 +2634,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('events') ->inject('mode') ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $events, string $mode) { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data)) { @@ -2611,16 +2645,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } @@ -2637,7 +2671,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') // Add permissions for current the user if none were provided. if (\is_null($permissions)) { $permissions = []; - if (! empty($user->getId())) { + if (!empty($user->getId())) { foreach ($allowedPermissions as $permission) { $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); } @@ -2646,7 +2680,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles)) { + if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -2658,8 +2692,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (! Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } } @@ -2675,20 +2709,20 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $validator = new Authorization($permission); $valid = $validator->isValid($collection->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && ! $documentSecurity) || ! $valid) { + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } if ($permission === Database::PERMISSION_UPDATE) { $valid = $valid || $validator->isValid($document->getUpdate()); - if ($documentSecurity && ! $valid) { + if ($documentSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } } $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -2708,21 +2742,21 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { if ( \is_array($relation) && \array_values($relation) !== $relation - && ! isset($relation['$id']) + && !isset($relation['$id']) ) { $relation['$id'] = ID::unique(); $relation = new Document($relation); } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId(), $relation->getId()) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) ); if ($current->isEmpty()) { @@ -2752,46 +2786,46 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $checkPermissions($collection, $document, Database::PERMISSION_CREATE); - try { - $document = $dbForProject->createDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $document); - } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage()); - } catch (DuplicateException $exception) { - throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); - } + try { + $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); + } catch (StructureException $exception) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage()); + } catch (DuplicateException $exception) { + throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (! \is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); - } + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); } } - }; + } + }; $processDocument($collection, $document); @@ -2822,36 +2856,37 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') ->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 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('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) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - if (! $collection->getAttribute('documentSecurity', false)) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if (!$collection->getAttribute('documentSecurity', false)) { $validator = new Authorization(Database::PERMISSION_READ); - if (! $validator->isValid($collection->getRead())) { + if (!$validator->isValid($collection->getRead())) { $collection = new Document(); } } } - if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { + if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Validate queries $queriesValidator = new Documents($collection->getAttribute('attributes'), $collection->getAttribute('indexes')); $validQueries = $queriesValidator->isValid($queries); - if (! $validQueries) { + if (!$validQueries) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $queriesValidator->getDescription()); } @@ -2863,7 +2898,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') if ($cursor) { $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId)); + $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -2874,8 +2909,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $filterQueries = Query::groupByType($queries)['filters']; - $documents = $dbForProject->find('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $queries); - $total = $dbForProject->count('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT); // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { @@ -2889,7 +2924,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -2898,18 +2933,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') if (empty($related)) { continue; } - if (! \is_array($related)) { + if (!\is_array($related)) { $relations = [$related]; } else { $relations = $related; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { - if (! $processDocument($relatedCollection, $doc)) { + if (!$processDocument($relatedCollection, $doc)) { unset($relations[$index]); } } @@ -2926,9 +2961,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') }; // The linter is forcing this indentation - foreach ($documents as $document) { - $processDocument($collection, $document); - } + foreach ($documents as $document) { + $processDocument($collection, $document); + } $response->dynamic(new Document([ 'total' => $total, @@ -2958,16 +2993,17 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->inject('dbForProject') ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } @@ -2975,13 +3011,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen // Validate queries $queriesValidator = new DocumentQueriesValidator($collection->getAttribute('attributes')); $validQueries = $queriesValidator->isValid($queries); - if (! $validQueries) { + if (!$validQueries) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $queriesValidator->getDescription()); } $queries = Query::parseQueries($queries); - $document = $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId, $queries); + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -2998,7 +3034,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3007,13 +3043,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen if (empty($related)) { continue; } - if (! \is_array($related)) { + if (!\is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3050,19 +3086,20 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->inject('locale') ->inject('geodb') ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $document = $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId); + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3074,13 +3111,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'database/'.$databaseId.'/collection/'.$collectionId.'/document/'.$document->getId(); + $resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -3108,14 +3145,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -3158,29 +3195,30 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->inject('events') ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $events, string $mode) { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data) && \is_null($permissions)) { throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } // Read permission should not be required for update /** @var Document $document */ - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3195,7 +3233,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles) && ! \is_null($permissions)) { + if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -3207,8 +3245,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (! Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } } @@ -3228,7 +3266,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) { $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3248,7 +3286,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -3256,14 +3294,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum if ( \is_array($relation) && \array_values($relation) !== $relation - && ! isset($relation['$id']) + && !isset($relation['$id']) ) { $relation['$id'] = ID::unique(); $relation = new Document($relation); } if ($relation instanceof Document) { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId(), + $oldDocument = Authorization::skip(fn() => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -3271,7 +3309,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId() + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() ); if ($oldDocument->isEmpty()) { @@ -3296,8 +3334,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, - fn () => $dbForProject->updateDocument( - 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), + fn() => $dbForProject->updateDocument( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document->getId(), $newDocument ) @@ -3317,7 +3355,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3326,13 +3364,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum if (empty($related)) { continue; } - if (! \is_array($related)) { + if (!\is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3384,22 +3422,23 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('deletes') ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $events, Delete $deletes, string $mode) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty() || (! $database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty() || (!$database->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - if ($collection->isEmpty() || ! $collection->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3410,18 +3449,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $validator = new Authorization(Database::PERMISSION_DELETE); $valid = $validator->isValid($collection->getDelete()); - if (! $documentSecurity && ! $valid) { + if (!$documentSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $valid = $valid || $validator->isValid($document->getDelete()); - if ($documentSecurity && ! $valid) { + if ($documentSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3430,13 +3469,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu if (empty($related)) { continue; } - if (! \is_array($related)) { + if (!\is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3452,10 +3491,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $checkPermissions($collection, $document); - Authorization::skip(fn () => $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { + Authorization::skip(fn() => $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { try { $dbForProject->deleteDocument( - 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId ); } catch (RestrictedException) { @@ -3464,7 +3503,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu })); $dbForProject->deleteCachedDocument( - 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId ); @@ -3475,7 +3514,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -3484,13 +3523,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu if (empty($related)) { continue; } - if (! \is_array($related)) { + if (!\is_array($related)) { $related = [$related]; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_'.$database->getInternalId(), $relatedCollectionId) + fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3532,6 +3571,7 @@ App::get('/v1/databases/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { + $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -3565,23 +3605,23 @@ App::get('/v1/databases/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } $response->dynamic(new Document([ 'range' => $range, - 'databasesTotal' => $usage[$metrics[0]], + 'databasesTotal' => $usage[$metrics[0]], 'collectionsTotal' => $usage[$metrics[1]], - 'documentsTotal' => $usage[$metrics[2]], + 'documentsTotal' => $usage[$metrics[2]], ]), Response::MODEL_USAGE_DATABASES); }); @@ -3600,7 +3640,8 @@ App::get('/v1/databases/:databaseId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) { - $database = $dbForProject->getDocument('databases', $databaseId); + + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -3638,23 +3679,23 @@ App::get('/v1/databases/:databaseId/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } $response->dynamic(new Document([ 'range' => $range, - 'collectionsTotal' => $usage[$metrics[0]], - 'documentsTotal' => $usage[$metrics[1]], + 'collectionsTotal' => $usage[$metrics[0]], + 'documentsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_DATABASE); }); @@ -3675,9 +3716,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { - $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_'.$database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_'.$database->getInternalId().'_collection_'.$collectionDocument->getInternalId()); + + $database = $dbForProject->getDocument('databases', $databaseId); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3714,21 +3756,21 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } $response->dynamic(new Document([ 'range' => $range, - 'documentsTotal' => $usage[$metrics[0]], + 'documentsTotal' => $usage[$metrics[0]], ]), Response::MODEL_USAGE_COLLECTION); }); diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index b7baf560bb..81500f1d27 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -9,40 +9,40 @@ use Appwrite\Event\Func; use Appwrite\Event\Usage; use Appwrite\Event\Validator\Event as ValidatorEvent; use Appwrite\Extend\Exception; -use Appwrite\Task\Validator\Cron; use Appwrite\Utopia\Database\Validator\CustomId; -use Appwrite\Utopia\Database\Validator\Queries\Deployments; -use Appwrite\Utopia\Database\Validator\Queries\Executions; -use Appwrite\Utopia\Database\Validator\Queries\Functions; -use Appwrite\Utopia\Response; -use Executor\Executor; -use Utopia\App; -use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Roles; use Utopia\Database\Validator\UID; use Utopia\Storage\Device; use Utopia\Storage\Validator\File; use Utopia\Storage\Validator\FileExt; use Utopia\Storage\Validator\FileSize; use Utopia\Storage\Validator\Upload; +use Appwrite\Utopia\Response; use Utopia\Swoole\Request; +use Appwrite\Task\Validator\Cron; +use Appwrite\Utopia\Database\Validator\Queries\Deployments; +use Appwrite\Utopia\Database\Validator\Queries\Executions; +use Appwrite\Utopia\Database\Validator\Queries\Functions; +use Utopia\App; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\DateTime; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Validator\ArrayList; -use Utopia\Validator\Boolean; -use Utopia\Validator\Range; use Utopia\Validator\Text; +use Utopia\Validator\Range; use Utopia\Validator\WhiteList; +use Utopia\Config\Config; +use Executor\Executor; +use Utopia\CLI\Console; +use Utopia\Database\Validator\Roles; +use Utopia\Validator\Boolean; +use Utopia\Database\Exception\Duplicate as DuplicateException; -include_once __DIR__.'/../shared/api.php'; +include_once __DIR__ . '/../shared/api.php'; App::post('/v1/functions') ->groups(['api', 'functions']) @@ -60,9 +60,9 @@ App::post('/v1/functions') ->label('sdk.response.model', Response::MODEL_FUNCTION) ->param('functionId', '', new CustomId(), 'Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 64 characters long.', true) + ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.') - ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.', true) + ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.', true) ->param('enabled', true, new Boolean(), 'Is function enabled?', true) @@ -73,6 +73,7 @@ App::post('/v1/functions') ->inject('events') ->inject('dbForConsole') ->action(function (string $functionId, string $name, array $execute, string $runtime, array $events, string $schedule, int $timeout, bool $enabled, Response $response, Database $dbForProject, Document $project, Document $user, Event $eventsInstance, Database $dbForConsole) { + $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; $function = $dbForProject->createDocument('functions', new Document([ '$id' => $functionId, @@ -86,18 +87,18 @@ App::post('/v1/functions') 'schedule' => $schedule, 'scheduleInternalId' => '', 'timeout' => $timeout, - 'search' => implode(' ', [$functionId, $name, $runtime]), + 'search' => implode(' ', [$functionId, $name, $runtime]) ])); $schedule = Authorization::skip( - fn () => $dbForConsole->createDocument('schedules', new Document([ + fn() => $dbForConsole->createDocument('schedules', new Document([ 'region' => App::getEnv('_APP_REGION', 'default'), // Todo replace with projects region 'resourceType' => 'function', 'resourceId' => $function->getId(), 'resourceInternalId' => $function->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), - 'schedule' => $function->getAttribute('schedule'), + 'schedule' => $function->getAttribute('schedule'), 'active' => false, ])) ); @@ -124,14 +125,15 @@ App::get('/v1/functions') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_FUNCTION_LIST) - ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -171,17 +173,17 @@ App::get('/v1/functions/runtimes') ->label('sdk.response.model', Response::MODEL_RUNTIME_LIST) ->inject('response') ->action(function (Response $response) { + $runtimes = Config::getParam('runtimes'); $runtimes = array_map(function ($key) use ($runtimes) { $runtimes[$key]['$id'] = $key; - return $runtimes[$key]; }, array_keys($runtimes)); $response->dynamic(new Document([ 'total' => count($runtimes), - 'runtimes' => $runtimes, + 'runtimes' => $runtimes ]), Response::MODEL_RUNTIME_LIST); }); @@ -224,6 +226,7 @@ App::get('/v1/functions/:functionId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $functionId, string $range, Response $response, Database $dbForProject) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -267,18 +270,18 @@ App::get('/v1/functions/:functionId/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } $response->dynamic(new Document([ 'range' => $range, @@ -306,6 +309,7 @@ App::get('/v1/functions/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { + $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -344,18 +348,18 @@ App::get('/v1/functions/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } $response->dynamic(new Document([ 'range' => $range, 'functionsTotal' => $usage[$metrics[0]], @@ -385,8 +389,8 @@ App::put('/v1/functions/:functionId') ->label('sdk.response.model', Response::MODEL_FUNCTION) ->param('functionId', '', new UID(), 'Function ID.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 64 characters long.', true) - ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.', true) + ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) + ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Maximum execution time in seconds.', true) ->param('enabled', true, new Boolean(), 'Is function enabled?', true) @@ -397,6 +401,7 @@ App::put('/v1/functions/:functionId') ->inject('events') ->inject('dbForConsole') ->action(function (string $functionId, string $name, array $execute, array $events, string $schedule, int $timeout, bool $enabled, Response $response, Database $dbForProject, Document $project, Document $user, Event $eventsInstance, Database $dbForConsole) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -419,7 +424,7 @@ App::put('/v1/functions/:functionId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $eventsInstance->setParam('functionId', $function->getId()); @@ -449,6 +454,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') ->inject('events') ->inject('dbForConsole') ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $events, Database $dbForConsole) { + $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); @@ -478,7 +484,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $events @@ -509,13 +515,14 @@ App::delete('/v1/functions/:functionId') ->inject('project') ->inject('dbForConsole') ->action(function (string $functionId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Document $project, Database $dbForConsole) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } - if (! $dbForProject->deleteDocument('functions', $function->getId())) { + if (!$dbForProject->deleteDocument('functions', $function->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove function from DB'); } @@ -563,6 +570,7 @@ App::post('/v1/functions/:functionId/deployments') ->inject('deviceLocal') ->inject('dbForConsole') ->action(function (string $functionId, string $entrypoint, mixed $code, bool $activate, Request $request, Response $response, Database $dbForProject, Event $events, Document $project, Device $deviceFunctions, Device $deviceLocal, Database $dbForConsole) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -589,7 +597,7 @@ App::post('/v1/functions/:functionId/deployments') $fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name']; $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; - if (! $fileExt->isValid($file['name'])) { // Check if file type is allowed + if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED); } @@ -598,7 +606,7 @@ App::post('/v1/functions/:functionId/deployments') $chunk = 1; $chunks = 1; - if (! empty($contentRange)) { + if (!empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); @@ -619,21 +627,21 @@ App::post('/v1/functions/:functionId/deployments') } } - if (! $fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit + if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); } - if (! $upload->isValid($fileTmpName)) { + if (!$upload->isValid($fileTmpName)) { throw new Exception(Exception::STORAGE_INVALID_FILE); } // Save to storage $fileSize ??= $deviceLocal->getFileSize($fileTmpName); - $path = $deviceFunctions->getPath($deploymentId.'.'.\pathinfo($fileName, PATHINFO_EXTENSION)); + $path = $deviceFunctions->getPath($deploymentId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); $deployment = $dbForProject->getDocument('deployments', $deploymentId); $metadata = ['content_type' => $deviceLocal->getFileMimeType($fileTmpName)]; - if (! $deployment->isEmpty()) { + if (!$deployment->isEmpty()) { $chunks = $deployment->getAttribute('chunksTotal', 1); $metadata = $deployment->getAttribute('metadata', []); if ($chunk === -1) { @@ -655,7 +663,7 @@ App::post('/v1/functions/:functionId/deployments') $activeDeployments = $dbForProject->find('deployments', [ Query::equal('activate', [true]), Query::equal('resourceId', [$functionId]), - Query::equal('resourceType', ['functions']), + Query::equal('resourceType', ['functions']) ]); foreach ($activeDeployments as $activeDeployment) { @@ -747,11 +755,12 @@ App::get('/v1/functions/:functionId/deployments') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST) ->param('functionId', '', new UID(), 'Function ID.') - ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -760,7 +769,7 @@ App::get('/v1/functions/:functionId/deployments') $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -818,6 +827,7 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId') ->inject('response') ->inject('dbForProject') ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -863,6 +873,7 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') ->inject('events') ->inject('deviceFunctions') ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Device $deviceFunctions) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -878,7 +889,7 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') } if ($deviceFunctions->delete($deployment->getAttribute('path', ''))) { - if (! $dbForProject->deleteDocument('deployments', $deployment->getId())) { + if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); } } @@ -922,6 +933,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') ->inject('project') ->inject('events') ->action(function (string $functionId, string $deploymentId, string $buildId, Response $response, Database $dbForProject, Document $project, Event $events) { + $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -986,10 +998,11 @@ App::post('/v1/functions/:functionId/executions') ->inject('queueForFunctions') ->inject('queueForUsage') ->action(function (string $functionId, string $data, bool $async, Response $response, Document $project, Database $dbForProject, Document $user, Event $events, string $mode, Func $queueForFunctions, Usage $queueForUsage) { + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - if ($function->isEmpty() || ! $function->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($function->isEmpty() || !$function->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } } @@ -999,7 +1012,7 @@ App::post('/v1/functions/:functionId/executions') $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; if (\is_null($runtime)) { - throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); + throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); @@ -1024,7 +1037,7 @@ App::post('/v1/functions/:functionId/executions') $validator = new Authorization('execute'); - if (! $validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function + if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } @@ -1033,7 +1046,7 @@ App::post('/v1/functions/:functionId/executions') /** @var Document $execution */ $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', new Document([ '$id' => $executionId, - '$permissions' => ! $user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], + '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], 'functionInternalId' => $function->getInternalId(), 'functionId' => $function->getId(), 'deploymentInternalId' => $deployment->getInternalId(), @@ -1048,7 +1061,7 @@ App::post('/v1/functions/:functionId/executions') ]))); $jwt = ''; // initialize - if (! $user->isEmpty()) { // If userId exists, generate a JWT for function + if (!$user->isEmpty()) { // If userId exists, generate a JWT for function $sessions = $user->getAttribute('sessions', []); $current = new Document(); @@ -1059,7 +1072,7 @@ App::post('/v1/functions/:functionId/executions') } } - if (! $current->isEmpty()) { + if (!$current->isEmpty()) { $jwtObj = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway. $jwt = $jwtObj->encode([ 'userId' => $user->getId(), @@ -1091,7 +1104,6 @@ App::post('/v1/functions/:functionId/executions') $vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) { $carry[$var->getAttribute('key')] = $var->getAttribute('value') ?? ''; - return $carry; }, []); @@ -1133,13 +1145,13 @@ App::post('/v1/functions/:functionId/executions') * Sync execution compute usage from */ $queueForUsage - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int) ($executionResponse['duration'] * 1000))// per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int) ($executionResponse['duration'] * 1000))// per function -; + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($executionResponse['duration'] * 1000))// per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($executionResponse['duration'] * 1000))// per function + ; } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); $execution - ->setAttribute('duration', (float) $interval->format('%s.%f')) + ->setAttribute('duration', (float)$interval->format('%s.%f')) ->setAttribute('status', 'failed') ->setAttribute('statusCode', $th->getCode()) ->setAttribute('stderr', $th->getMessage()); @@ -1152,7 +1164,7 @@ App::post('/v1/functions/:functionId/executions') $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); - if (! $isPrivilegedUser && ! $isAppUser) { + if (!$isPrivilegedUser && !$isAppUser) { $execution->setAttribute('stdout', ''); $execution->setAttribute('stderr', ''); } @@ -1174,23 +1186,24 @@ App::get('/v1/functions/:functionId/executions') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_EXECUTION_LIST) ->param('functionId', '', new UID(), 'Function ID.') - ->param('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('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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - if ($function->isEmpty() || ! $function->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($function->isEmpty() || !$function->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } } $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -1220,11 +1233,10 @@ App::get('/v1/functions/:functionId/executions') $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); - if (! $isPrivilegedUser && ! $isAppUser) { + if (!$isPrivilegedUser && !$isAppUser) { $results = array_map(function ($execution) { $execution->setAttribute('stdout', ''); $execution->setAttribute('stderr', ''); - return $execution; }, $results); } @@ -1252,10 +1264,11 @@ App::get('/v1/functions/:functionId/executions/:executionId') ->inject('dbForProject') ->inject('mode') ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, string $mode) { + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - if ($function->isEmpty() || ! $function->getAttribute('enabled')) { - if (! ($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { + if ($function->isEmpty() || !$function->getAttribute('enabled')) { + if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { throw new Exception(Exception::FUNCTION_NOT_FOUND); } } @@ -1273,7 +1286,7 @@ App::get('/v1/functions/:functionId/executions/:executionId') $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); - if (! $isPrivilegedUser && ! $isAppUser) { + if (!$isPrivilegedUser && !$isAppUser) { $execution->setAttribute('stdout', ''); $execution->setAttribute('stderr', ''); } @@ -1297,7 +1310,7 @@ App::post('/v1/functions/:functionId/variables') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_VARIABLE) ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: '.Database::LENGTH_KEY.' chars.', false) + ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) ->inject('response') ->inject('dbForProject') @@ -1335,7 +1348,7 @@ App::post('/v1/functions/:functionId/variables') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $dbForProject->deleteCachedDocument('functions', $function->getId()); @@ -1344,7 +1357,7 @@ App::post('/v1/functions/:functionId/variables') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $response @@ -1434,6 +1447,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') ->inject('dbForProject') ->inject('dbForConsole') ->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole) { + $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -1452,7 +1466,8 @@ App::put('/v1/functions/:functionId/variables/:variableId') $variable ->setAttribute('key', $key) ->setAttribute('value', $value ?? $variable->getAttribute('value')) - ->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key])); + ->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key])) + ; try { $dbForProject->updateDocument('variables', $variable->getId(), $variable); @@ -1464,7 +1479,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $dbForProject->deleteCachedDocument('functions', $function->getId()); @@ -1473,7 +1488,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); @@ -1518,7 +1533,7 @@ App::delete('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $dbForProject->deleteCachedDocument('functions', $function->getId()); @@ -1527,7 +1542,7 @@ App::delete('/v1/functions/:functionId/variables/:variableId') $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index b4eb5ef620..8ee3b5ac47 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -42,11 +42,11 @@ App::get('/v1/graphql') 'query' => $query, ]; - if (! empty($operationName)) { + if (!empty($operationName)) { $query['operationName'] = $operationName; } - if (! empty($variables)) { + if (!empty($variables)) { $query['variables'] = \json_decode($variables, true); } @@ -150,11 +150,10 @@ App::post('/v1/graphql') /** * Execute a GraphQL request * - * @param GQLSchema $schema - * @param Adapter $promiseAdapter - * @param array $query + * @param GQLSchema $schema + * @param Adapter $promiseAdapter + * @param array $query * @return array - * * @throws Exception */ function execute( @@ -166,7 +165,7 @@ function execute( $maxComplexity = App::getEnv('_APP_GRAPHQL_MAX_COMPLEXITY', 250); $maxDepth = App::getEnv('_APP_GRAPHQL_MAX_DEPTH', 3); - if (! empty($query) && ! isset($query[0])) { + if (!empty($query) && !isset($query[0])) { $query = [$query]; } if (empty($query)) { @@ -225,7 +224,7 @@ function execute( /** * Parse an "application/graphql" type request * - * @param Request $request + * @param Request $request * @return array */ function parseGraphql(Request $request): array @@ -236,8 +235,8 @@ function parseGraphql(Request $request): array /** * Parse an "multipart/form-data" type request * - * @param array $query - * @param Request $request + * @param array $query + * @param Request $request * @return array */ function parseMultipart(array $query, Request $request): array @@ -249,7 +248,7 @@ function parseMultipart(array $query, Request $request): array foreach ($locations as $location) { $items = &$operations; foreach (\explode('.', $location) as $key) { - if (! isset($items[$key]) || ! \is_array($items[$key])) { + if (!isset($items[$key]) || !\is_array($items[$key])) { $items[$key] = []; } $items = &$items[$key]; @@ -277,7 +276,7 @@ function parseMultipart(array $query, Request $request): array function processResult($result, $debugFlags): array { // Only one query, return the result - if (! isset($result[1])) { + if (!isset($result[1])) { return $result[0]->toArray($debugFlags); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 4cac066cc6..d6a2612f32 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -28,10 +28,11 @@ App::get('/v1/health') ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) ->inject('response') ->action(function (Response $response) { + $output = [ 'name' => 'http', 'status' => 'pass', - 'ping' => 0, + 'ping' => 0 ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -46,7 +47,7 @@ App::get('/v1/health/version') ->label('sdk.response.model', Response::MODEL_HEALTH_VERSION) ->inject('response') ->action(function (Response $response) { - $response->dynamic(new Document(['version' => APP_VERSION_STABLE]), Response::MODEL_HEALTH_VERSION); + $response->dynamic(new Document([ 'version' => APP_VERSION_STABLE ]), Response::MODEL_HEALTH_VERSION); }); App::get('/v1/health/db') @@ -63,6 +64,7 @@ App::get('/v1/health/db') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { + $output = []; $configs = [ @@ -79,22 +81,22 @@ App::get('/v1/health/db') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } @@ -120,6 +122,7 @@ App::get('/v1/health/cache') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { + $output = []; $configs = [ @@ -135,22 +138,22 @@ App::get('/v1/health/cache') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } @@ -176,6 +179,7 @@ App::get('/v1/health/queue') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { + $output = []; $configs = [ @@ -191,22 +195,22 @@ App::get('/v1/health/queue') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } @@ -232,6 +236,7 @@ App::get('/v1/health/pubsub') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { + $output = []; $configs = [ @@ -247,22 +252,22 @@ App::get('/v1/health/pubsub') if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } catch (\Throwable $th) { $output[] = new Document([ - 'name' => $key." ($database)", + 'name' => $key . " ($database)", 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } } @@ -287,6 +292,7 @@ App::get('/v1/health/time') ->label('sdk.response.model', Response::MODEL_HEALTH_TIME) ->inject('response') ->action(function (Response $response) { + /* * Code from: @see https://www.beliefmedia.com.au/query-ntp-time-server */ @@ -299,7 +305,7 @@ App::get('/v1/health/time') \socket_connect($sock, $host, 123); /* Send request */ - $msg = "\010".\str_repeat("\0", 47); + $msg = "\010" . \str_repeat("\0", 47); \socket_send($sock, $msg, \strlen($msg), 0); @@ -324,7 +330,7 @@ App::get('/v1/health/time') $output = [ 'remoteTime' => $timestamp, 'localTime' => \time(), - 'diff' => $diff, + 'diff' => $diff ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_TIME); @@ -343,7 +349,8 @@ App::get('/v1/health/queue/webhooks') ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->action(function (Response $response) { - $response->dynamic(new Document(['size' => Resque::size(Event::WEBHOOK_QUEUE_NAME)]), Response::MODEL_HEALTH_QUEUE); + + $response->dynamic(new Document([ 'size' => Resque::size(Event::WEBHOOK_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/queue/logs') @@ -359,7 +366,8 @@ App::get('/v1/health/queue/logs') ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->action(function (Response $response) { - $response->dynamic(new Document(['size' => Resque::size(Event::AUDITS_QUEUE_NAME)]), Response::MODEL_HEALTH_QUEUE); + + $response->dynamic(new Document([ 'size' => Resque::size(Event::AUDITS_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/queue/certificates') @@ -375,7 +383,8 @@ App::get('/v1/health/queue/certificates') ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->action(function (Response $response) { - $response->dynamic(new Document(['size' => Resque::size(Event::CERTIFICATES_QUEUE_NAME)]), Response::MODEL_HEALTH_QUEUE); + + $response->dynamic(new Document([ 'size' => Resque::size(Event::CERTIFICATES_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/queue/functions') @@ -393,7 +402,7 @@ App::get('/v1/health/queue/functions') ->inject('response') ->action(function (Connection $queue, Response $response) { $client = new Client(Event::FUNCTIONS_QUEUE_NAME, $queue); - $response->dynamic(new Document(['size' => $client->sumProcessingJobs()]), Response::MODEL_HEALTH_QUEUE); + $response->dynamic(new Document([ 'size' => $client->sumProcessingJobs() ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); App::get('/v1/health/storage/local') @@ -409,30 +418,31 @@ App::get('/v1/health/storage/local') ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) ->inject('response') ->action(function (Response $response) { + $checkStart = \microtime(true); foreach ( [ - 'Uploads' => APP_STORAGE_UPLOADS, - 'Cache' => APP_STORAGE_CACHE, - 'Config' => APP_STORAGE_CONFIG, - 'Certs' => APP_STORAGE_CERTIFICATES, + 'Uploads' => APP_STORAGE_UPLOADS, + 'Cache' => APP_STORAGE_CACHE, + 'Config' => APP_STORAGE_CONFIG, + 'Certs' => APP_STORAGE_CERTIFICATES ] as $key => $volume ) { $device = new Local($volume); - if (! \is_readable($device->getRoot())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device '.$key.' dir is not readable'); + if (!\is_readable($device->getRoot())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device ' . $key . ' dir is not readable'); } - if (! \is_writable($device->getRoot())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device '.$key.' dir is not writable'); + if (!\is_writable($device->getRoot())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device ' . $key . ' dir is not writable'); } } $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000), + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -451,9 +461,10 @@ App::get('/v1/health/anti-virus') ->label('sdk.response.model', Response::MODEL_HEALTH_ANTIVIRUS) ->inject('response') ->action(function (Response $response) { + $output = [ 'status' => '', - 'version' => '', + 'version' => '' ]; if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'disabled') { // Check if scans are enabled @@ -488,6 +499,7 @@ App::get('/v1/health/stats') // Currently only used internally ->inject('register') ->inject('deviceFiles') ->action(function (Response $response, Registry $register, Device $deviceFiles) { + $cache = $register->get('cache'); $cacheStats = $cache->info(); @@ -495,7 +507,7 @@ App::get('/v1/health/stats') // Currently only used internally $response ->json([ 'storage' => [ - 'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot().'/')), + 'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot() . '/')), 'partitionTotal' => Storage::human($deviceFiles->getPartitionTotalSpace()), 'partitionFree' => Storage::human($deviceFiles->getPartitionFreeSpace()), ], diff --git a/app/controllers/api/locale.php b/app/controllers/api/locale.php index 5fd423349a..29b4932543 100644 --- a/app/controllers/api/locale.php +++ b/app/controllers/api/locale.php @@ -1,7 +1,7 @@ getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - $output['continent'] = $locale->getText('continents.'.strtolower($record['continent']['code']), $locale->getText('locale.country.unknown')); + $output['country'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output['continent'] = $locale->getText('continents.' . strtolower($record['continent']['code']), $locale->getText('locale.country.unknown')); $output['continentCode'] = $record['continent']['code']; $output['eu'] = (\in_array($record['country']['iso_code'], $eu)) ? true : false; @@ -62,9 +62,9 @@ App::get('/v1/locale') } $response - ->addHeader('Cache-Control', 'public, max-age='.$time) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache -; + ->addHeader('Cache-Control', 'public, max-age=' . $time) + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache + ; $response->dynamic(new Document($output), Response::MODEL_LOCALE); }); @@ -111,7 +111,7 @@ App::get('/v1/locale/countries') foreach ($list as $value) { $output[] = new Document([ - 'name' => $locale->getText('countries.'.strtolower($value)), + 'name' => $locale->getText('countries.' . strtolower($value)), 'code' => $value, ]); } @@ -143,9 +143,9 @@ App::get('/v1/locale/countries/eu') $output = []; foreach ($eu as $code) { - if ($locale->getText('countries.'.strtolower($code), false) !== false) { + if ($locale->getText('countries.' . strtolower($code), false) !== false) { $output[] = new Document([ - 'name' => $locale->getText('countries.'.strtolower($code)), + 'name' => $locale->getText('countries.' . strtolower($code)), 'code' => $code, ]); } @@ -180,11 +180,11 @@ App::get('/v1/locale/countries/phones') \asort($list); foreach ($list as $code => $name) { - if ($locale->getText('countries.'.strtolower($code), false) !== false) { + if ($locale->getText('countries.' . strtolower($code), false) !== false) { $output[] = new Document([ - 'code' => '+'.$list[$code], + 'code' => '+' . $list[$code], 'countryCode' => $code, - 'countryName' => $locale->getText('countries.'.strtolower($code)), + 'countryName' => $locale->getText('countries.' . strtolower($code)), ]); } } @@ -212,7 +212,7 @@ App::get('/v1/locale/continents') foreach ($list as $value) { $output[] = new Document([ - 'name' => $locale->getText('continents.'.strtolower($value)), + 'name' => $locale->getText('continents.' . strtolower($value)), 'code' => $value, ]); } @@ -246,6 +246,7 @@ App::get('/v1/locale/currencies') $response->dynamic(new Document(['currencies' => $list, 'total' => \count($list)]), Response::MODEL_CURRENCY_LIST); }); + App::get('/v1/locale/languages') ->desc('List Languages') ->groups(['api', 'locale']) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index a2d7cc6419..1ff95fbeea 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -25,35 +25,35 @@ App::get('/v1/messaging/providers') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) - ->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('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) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, Database $dbForProject, Response $response) { - $queries = Query::parseQueries($queries); + $queries = Query::parseQueries($queries); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); - $cursor = reset($cursor); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); - if ($cursor) { - $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ - Query::equal('$id', [$providerId]), - Query::limit(1), - ])); + if ($cursor) { + $providerId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ + Query::equal('$id', [$providerId]), + Query::limit(1), + ])); - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); - } + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); + } - $cursor->setValue($cursorDocument[0]); - } + $cursor->setValue($cursorDocument[0]); + } - $filterQueries = Query::groupByType($queries)['filters']; - $response->dynamic(new Document([ - 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), - 'indexes' => $dbForProject->find('providers', $queries), - ]), Response::MODEL_PROVIDER_LIST); + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), + 'indexes' => $dbForProject->find('providers', $queries), + ]), Response::MODEL_PROVIDER_LIST); }); App::get('/v1/messaging/providers/:id') @@ -71,13 +71,13 @@ App::get('/v1/messaging/providers/:id') ->inject('dbForProject') ->inject('response') ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $response->dynamic($provider, Response::MODEL_PROVIDER); + $response->dynamic($provider, Response::MODEL_PROVIDER); }); /** @@ -101,18 +101,18 @@ App::post('/v1/messaging/providers/mailgun') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'mailgun', - 'type' => 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - 'domain' => $domain, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'mailgun', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + 'domain' => $domain, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/mailgun') @@ -134,39 +134,39 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'mailgun') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'mailgun') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey || $domain) { - // Check if all five variables are present - if ($apiKey && $domain) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'domain' => $domain, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($apiKey || $domain) { + // Check if all five variables are present + if ($apiKey && $domain) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'domain' => $domain + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/sendgrid') @@ -186,17 +186,17 @@ App::post('/v1/messaging/providers/sendgrid') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'sendgrid', - 'type' => 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'sendgrid', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/sendgrid') @@ -217,32 +217,32 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'sendgrid') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'sendgrid') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - ]); - } + if ($apiKey) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey + ]); + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); /** @@ -266,18 +266,18 @@ App::post('/v1/messaging/providers/msg91') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'msg91', - 'type' => 'sms', - 'credentials' => [ - 'senderId' => $senderId, - 'authKey' => $authKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'msg91', + 'type' => 'sms', + 'credentials' => [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/msg91') @@ -299,39 +299,39 @@ App::patch('/v1/messaging/providers/:id/msg91') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'msg91') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'msg91') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($senderId || $authKey) { - // Check if all five variables are present - if ($senderId && $authKey) { - $provider->setAttribute('credentials', [ - 'senderId' => $senderId, - 'authKey' => $authKey, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($senderId || $authKey) { + // Check if all five variables are present + if ($senderId && $authKey) { + $provider->setAttribute('credentials', [ + 'senderId' => $senderId, + 'authKey' => $authKey + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/telesign') @@ -352,18 +352,18 @@ App::post('/v1/messaging/providers/telesign') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'telesign', - 'type' => 'sms', - 'credentials' => [ - 'username' => $username, - 'password' => $password, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'telesign', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'password' => $password, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/telesign') @@ -385,39 +385,39 @@ App::patch('/v1/messaging/providers/:id/telesign') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'telesign') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'telesign') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($username || $password) { - // Check if all five variables are present - if ($username && $password) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'password' => $password, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($username || $password) { + // Check if all five variables are present + if ($username && $password) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'password' => $password + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/textmagic') @@ -438,18 +438,18 @@ App::post('/v1/messaging/providers/textmagic') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'text-magic', - 'type' => 'sms', - 'credentials' => [ - 'username' => $username, - 'apiKey' => $apiKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'text-magic', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/textmagic') @@ -471,39 +471,39 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'text-magic') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'text-magic') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($username || $apiKey) { - // Check if all five variables are present - if ($username && $apiKey) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'apiKey' => $apiKey, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($username || $apiKey) { + // Check if all five variables are present + if ($username && $apiKey) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'apiKey' => $apiKey + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/twilio') @@ -524,18 +524,18 @@ App::post('/v1/messaging/providers/twilio') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'twilio', - 'type' => 'sms', - 'credentials' => [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'twilio', + 'type' => 'sms', + 'credentials' => [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/twilio') @@ -557,39 +557,39 @@ App::patch('/v1/messaging/providers/:id/twilio') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'twilio') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'twilio') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($accountSid || $authToken) { - // Check if all five variables are present - if ($accountSid && $authToken) { - $provider->setAttribute('credentials', [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($accountSid || $authToken) { + // Check if all five variables are present + if ($accountSid && $authToken) { + $provider->setAttribute('credentials', [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/vonage') @@ -610,18 +610,18 @@ App::post('/v1/messaging/providers/vonage') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'vonage', - 'type' => 'sms', - 'credentials' => [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'vonage', + 'type' => 'sms', + 'credentials' => [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/vonage') @@ -643,39 +643,39 @@ App::patch('/v1/messaging/providers/:id/vonage') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'vonage') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'vonage') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey || $apiSecret) { - // Check if all five variables are present - if ($apiKey && $apiSecret) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($apiKey || $apiSecret) { + // Check if all five variables are present + if ($apiKey && $apiSecret) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); /** @@ -698,17 +698,17 @@ App::post('/v1/messaging/providers/fcm') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'fcm', - 'type' => 'push', - 'credentials' => [ - 'serverKey' => $serverKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'fcm', + 'type' => 'push', + 'credentials' => [ + 'serverKey' => $serverKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/fcm') @@ -729,30 +729,30 @@ App::patch('/v1/messaging/providers/:id/fcm') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'fcm') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'fcm') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($serverKey) { - $provider->setAttribute('credentials', ['serverKey' => $serverKey]); - } + if ($serverKey) { + $provider->setAttribute('credentials', ['serverKey' => $serverKey]); + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::post('/v1/messaging/providers/apns') @@ -776,21 +776,21 @@ App::post('/v1/messaging/providers/apns') ->inject('dbForProject') ->inject('response') ->action(function (string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'apns', - 'type' => 'push', - 'credentials' => [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'apns', + 'type' => 'push', + 'credentials' => [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::patch('/v1/messaging/providers/:id/apns') @@ -815,42 +815,42 @@ App::patch('/v1/messaging/providers/:id/apns') ->inject('dbForProject') ->inject('response') ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'apns') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); - } + if ($providerAttr !== 'apns') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { - // Check if all five variables are present - if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { - $provider->setAttribute('credentials', [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - } + if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { + // Check if all five variables are present + if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { + $provider->setAttribute('credentials', [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); }); App::delete('/v1/messaging/providers/:id') @@ -869,16 +869,16 @@ App::delete('/v1/messaging/providers/:id') ->inject('dbForProject') ->inject('response') ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $dbForProject->deleteDocument('providers', $provider->getId()); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $dbForProject->deleteDocument('providers', $provider->getId()); - $response->noContent(); + $response->noContent(); }); App::post('/v1/messaging/messages/email') @@ -904,30 +904,30 @@ App::post('/v1/messaging/messages/email') ->inject('events') ->inject('response') ->action(function (string $providerId, string $to, string $subject, string $content, string $from, string $html, DateTime $deliveryTime, Database $dbForProject, Event $eventsInstance, Response $response) { - $provider = $dbForProject->getDocument('providers', $providerId); + $provider = $dbForProject->getDocument('providers', $providerId); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $message = $dbForProject->createDocument('messages', new Document([ - 'providerId' => $provider->getId(), - 'providerInternalId' => $provider->getInternalId(), - 'to' => $to, - 'data' => [ - 'subject' => $subject, - 'content' => $content, - ], - 'deliveryTime' => $deliveryTime, - 'deliveryError' => null, - 'deliveredTo' => null, - 'delivered' => false, - 'search' => null, - ])); + $message = $dbForProject->createDocument('messages', new Document([ + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'to' => $to, + 'data' => [ + 'subject' => $subject, + 'content' => $content, + ], + 'deliveryTime' => $deliveryTime, + 'deliveryError' => null, + 'deliveredTo' => null, + 'delivered' => false, + 'search' => null, + ])); - $eventsInstance->setParam('messageId', $message->getId()); + $eventsInstance->setParam('messageId', $message->getId()); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_MESSAGE); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_MESSAGE); }); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 23ebc29362..8d961a0450 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -28,7 +28,7 @@ use Utopia\Validator\Text; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; -include_once __DIR__.'/../shared/api.php'; +include_once __DIR__ . '/../shared/api.php'; App::post('/v1/migrations/appwrite') ->groups(['api', 'migrations']) @@ -110,7 +110,7 @@ App::post('/v1/migrations/firebase/oauth') $firebase = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' + $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); $identity = $dbForConsole->findOne('identities', [ @@ -141,7 +141,7 @@ App::post('/v1/migrations/firebase/oauth') $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } @@ -167,7 +167,7 @@ App::post('/v1/migrations/firebase/oauth') 'resources' => $resources, 'statusCounters' => '{}', 'resourceData' => '{}', - 'errors' => [], + 'errors' => [] ])); $events->setParam('migrationId', $migration->getId()); @@ -368,14 +368,14 @@ App::get('/v1/migrations') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MIGRATION_LIST) - ->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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -505,7 +505,7 @@ App::get('/v1/migrations/firebase/report/oauth') $firebase = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' + $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); $identity = $dbForConsole->findOne('identities', [ @@ -536,7 +536,7 @@ App::get('/v1/migrations/firebase/report/oauth') $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } @@ -597,7 +597,7 @@ App::get('/v1/migrations/firebase/connect') $oauth2 = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' + $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); $url = $oauth2->getLoginURL(); @@ -611,7 +611,7 @@ App::get('/v1/migrations/firebase/redirect') ->desc('Capture and receive data on Firebase authorization') ->groups(['api', 'migrations']) ->label('scope', 'public') - ->label('error', __DIR__.'/../../views/general/error.phtml') + ->label('error', __DIR__ . '/../../views/general/error.phtml') ->param('code', '', new Text(2048), 'OAuth2 code.', true) ->inject('user') ->inject('project') @@ -635,7 +635,7 @@ App::get('/v1/migrations/firebase/redirect') $project = $dbForConsole->getDocument('projects', $projectId); if (empty($redirect)) { - $redirect = $request->getProtocol().'://'.$request->getHostname().'/console/project-$projectId/settings/migrations'; + $redirect = $request->getProtocol() . '://' . $request->getHostname() . '/console/project-$projectId/settings/migrations'; } if ($project->isEmpty()) { @@ -648,11 +648,11 @@ App::get('/v1/migrations/firebase/redirect') } // OAuth Authroization - if (! empty($code)) { + if (!empty($code)) { $oauth2 = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' + $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); $accessToken = $oauth2->getAccessToken($code); @@ -678,17 +678,17 @@ App::get('/v1/migrations/firebase/redirect') Query::equal('providerEmail', [$email]), ]); - if ($identity !== false && ! $identity->isEmpty()) { + if ($identity !== false && !$identity->isEmpty()) { if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } } - if ($identity !== false && ! $identity->isEmpty()) { + if ($identity !== false && !$identity->isEmpty()) { $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry)); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } else { @@ -706,7 +706,7 @@ App::get('/v1/migrations/firebase/redirect') 'providerEmail' => $email, 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry), + 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), ])); } } else { @@ -738,7 +738,7 @@ App::get('/v1/migrations/firebase/projects') $firebase = new OAuth2Firebase( App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol().'://'.$request->getHostname().'/v1/migrations/firebase/redirect' + $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); $identity = $dbForConsole->findOne('identities', [ @@ -781,7 +781,7 @@ App::get('/v1/migrations/firebase/projects') $identity = $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); $dbForConsole->updateDocument('identities', $identity->getId(), $identity); } @@ -964,7 +964,7 @@ App::delete('/v1/migrations/:migrationId') throw new Exception(Exception::MIGRATION_NOT_FOUND); } - if (! $dbForProject->deleteDocument('migrations', $migration->getId())) { + if (!$dbForProject->deleteDocument('migrations', $migration->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove migration from DB', 500); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 0146f1c19f..0f05c6f497 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -4,6 +4,7 @@ use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -23,6 +24,7 @@ App::get('/v1/project/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { + $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -35,7 +37,7 @@ App::get('/v1/project/usage') METRIC_DATABASES, METRIC_USERS, METRIC_BUCKETS, - METRIC_FILES_STORAGE, + METRIC_FILES_STORAGE ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -58,23 +60,25 @@ App::get('/v1/project/usage') } }); + $format = match ($days['period']) { '1h' => 'Y-m-d\TH:00:00.000P', '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } + $response->dynamic(new Document([ 'range' => $range, diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index f28f5197cb..6fff6b324b 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1,22 +1,19 @@ groups(['projects']) @@ -63,7 +64,7 @@ App::post('/v1/projects') ->param('projectId', '', new ProjectId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('teamId', '', new UID(), 'Team unique ID.') - ->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn ($config) => ! $config['disabled']))), 'Project Region.', true) + ->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn($config) => !$config['disabled']))), 'Project Region.', true) ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) ->param('logo', '', new Text(1024), 'Project logo.', true) ->param('url', '', new URL(), 'Project URL.', true) @@ -78,6 +79,8 @@ App::post('/v1/projects') ->inject('cache') ->inject('pools') ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools) { + + $team = $dbForConsole->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -161,7 +164,7 @@ App::post('/v1/projects') 'domains' => null, 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), - 'database' => $database, + 'database' => $database ])); } catch (Duplicate $th) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); @@ -198,7 +201,7 @@ App::post('/v1/projects') 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '', + 'format' => $attribute['format'] ?? '' ]); } @@ -229,14 +232,15 @@ App::get('/v1/projects') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT_LIST) - ->param('queries', [], new Projects(), '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('queries', [], new Projects(), '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) ->inject('response') ->inject('dbForConsole') ->action(function (array $queries, string $search, Response $response, Database $dbForConsole) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -277,6 +281,7 @@ App::get('/v1/projects/:projectId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -310,6 +315,7 @@ App::patch('/v1/projects/:projectId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -347,6 +353,7 @@ App::patch('/v1/projects/:projectId/team') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $teamId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); $team = $dbForConsole->getDocument('teams', $teamId); @@ -382,11 +389,12 @@ App::patch('/v1/projects/:projectId/service') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.') + ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -416,13 +424,14 @@ App::patch('/v1/projects/:projectId/service/all') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $allServices = array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])); + $allServices = array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])); $services = []; foreach ($allServices as $service) { @@ -452,6 +461,7 @@ App::patch('/v1/projects/:projectId/oauth2') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -461,15 +471,15 @@ App::patch('/v1/projects/:projectId/oauth2') $providers = $project->getAttribute('authProviders', []); if ($appId !== null) { - $providers[$provider.'Appid'] = $appId; + $providers[$provider . 'Appid'] = $appId; } if ($secret !== null) { - $providers[$provider.'Secret'] = $secret; + $providers[$provider . 'Secret'] = $secret; } if ($enabled !== null) { - $providers[$provider.'Enabled'] = $enabled; + $providers[$provider . 'Enabled'] = $enabled; } $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('authProviders', $providers)); @@ -492,6 +502,7 @@ App::patch('/v1/projects/:projectId/auth/limit') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -522,6 +533,7 @@ App::patch('/v1/projects/:projectId/auth/duration') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $duration, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -548,11 +560,12 @@ App::patch('/v1/projects/:projectId/auth/:method') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: '.implode(',', \array_keys(Config::getParam('auth'))), false) + ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false) ->param('status', false, new Boolean(true), 'Set the status of this auth method.') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); $auth = Config::getParam('auth')[$method] ?? []; $authKey = $auth['key'] ?? ''; @@ -581,10 +594,11 @@ App::patch('/v1/projects/:projectId/auth/password-history') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is'.APP_LIMIT_USER_PASSWORD_HISTORY.'. Default value is 0') + ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -615,6 +629,7 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -645,6 +660,7 @@ App::patch('/v1/projects/:projectId/auth/personal-data') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -671,10 +687,11 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-'.APP_LIMIT_USER_SESSIONS_MAX.'. Default is '.APP_LIMIT_USER_SESSIONS_DEFAULT) + ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -713,9 +730,10 @@ App::delete('/v1/projects/:projectId') $deletes ->setType(DELETE_TYPE_DOCUMENT) - ->setDocument($project); + ->setDocument($project) + ; - if (! $dbForConsole->deleteDocument('projects', $projectId)) { + if (!$dbForConsole->deleteDocument('projects', $projectId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB'); } @@ -736,7 +754,7 @@ App::post('/v1/projects/:projectId/webhooks') ->label('sdk.response.model', Response::MODEL_WEBHOOK) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') - ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.') + ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') ->param('url', null, new URL(['http', 'https']), 'Webhook URL.') ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) @@ -744,6 +762,7 @@ App::post('/v1/projects/:projectId/webhooks') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -793,6 +812,7 @@ App::get('/v1/projects/:projectId/webhooks') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -825,6 +845,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -856,7 +877,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') - ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.') + ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') ->param('url', null, new URL(['http', 'https']), 'Webhook URL.') ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) @@ -864,6 +885,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, string $name, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -887,7 +909,8 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('url', $url) ->setAttribute('security', $security) ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass); + ->setAttribute('httpPass', $httpPass) + ; $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); $dbForConsole->deleteCachedDocument('projects', $project->getId()); @@ -910,6 +933,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -947,6 +971,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -983,11 +1008,12 @@ App::post('/v1/projects/:projectId/keys') ->label('sdk.response.model', Response::MODEL_KEY) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') - ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' scopes are allowed.') + ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in ISO 8601 format. Use null for unlimited expiration.', true) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1034,6 +1060,7 @@ App::get('/v1/projects/:projectId/keys') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1066,6 +1093,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1097,11 +1125,12 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') - ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' events are allowed.') + ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in ISO 8601 format. Use null for unlimited expiration.', true) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1120,7 +1149,8 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key ->setAttribute('name', $name) ->setAttribute('scopes', $scopes) - ->setAttribute('expire', $expire); + ->setAttribute('expire', $expire) + ; $dbForConsole->updateDocument('keys', $key->getId(), $key); @@ -1143,6 +1173,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1205,7 +1236,7 @@ App::post('/v1/projects/:projectId/platforms') 'name' => $name, 'key' => $key, 'store' => $store, - 'hostname' => $hostname, + 'hostname' => $hostname ]); $platform = $dbForConsole->createDocument('platforms', $platform); @@ -1231,6 +1262,7 @@ App::get('/v1/projects/:projectId/platforms') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1263,6 +1295,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1319,7 +1352,8 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->setAttribute('name', $name) ->setAttribute('key', $key) ->setAttribute('store', $store) - ->setAttribute('hostname', $hostname); + ->setAttribute('hostname', $hostname) + ; $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); @@ -1342,6 +1376,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1381,6 +1416,7 @@ App::post('/v1/projects/:projectId/domains') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $domain, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1392,17 +1428,17 @@ App::post('/v1/projects/:projectId/domains') } $document = $dbForConsole->findOne('domains', [ - Query::equal('domain', [$domain]), + Query::equal('domain', [$domain]) ]); - if ($document && ! $document->isEmpty()) { + if ($document && !$document->isEmpty()) { throw new Exception(Exception::DOMAIN_ALREADY_EXISTS); } $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - if (! $target->isKnown() || $target->isTest()) { - throw new Exception(Exception::DOMAIN_TARGET_INVALID, 'Unreachable CNAME target ('.$target->get().'). Please check the _APP_DOMAIN_TARGET environment variable of your Appwrite server.'); + if (!$target->isKnown() || $target->isTest()) { + throw new Exception(Exception::DOMAIN_TARGET_INVALID, 'Unreachable CNAME target (' . $target->get() . '). Please check the _APP_DOMAIN_TARGET environment variable of your Appwrite server.'); } $domain = new Domain($domain); @@ -1447,6 +1483,7 @@ App::get('/v1/projects/:projectId/domains') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1479,6 +1516,7 @@ App::get('/v1/projects/:projectId/domains/:domainId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1512,6 +1550,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1529,8 +1568,8 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - if (! $target->isKnown() || $target->isTest()) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unreachable CNAME target ('.$target->get().'), please use a domain with a public suffix.'); + if (!$target->isKnown() || $target->isTest()) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.'); } if ($domain->getAttribute('verification') === true) { @@ -1539,10 +1578,11 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') $validator = new CNAME($target->get()); // Verify Domain with DNS records - if (! $validator->isValid($domain->getAttribute('domain', ''))) { + if (!$validator->isValid($domain->getAttribute('domain', ''))) { throw new Exception(Exception::DOMAIN_VERIFICATION_FAILED); } + $dbForConsole->updateDocument('domains', $domain->getId(), $domain->setAttribute('verification', true)); $dbForConsole->deleteCachedDocument('projects', $project->getId()); @@ -1570,6 +1610,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId') ->inject('dbForConsole') ->inject('deletes') ->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole, Delete $deletes) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1622,6 +1663,7 @@ App::patch('/v1/projects/:projectId/smtp') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, string $sender, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1639,7 +1681,7 @@ App::patch('/v1/projects/:projectId/smtp') $mail->SMTPAutoTLS = false; $valid = $mail->SmtpConnect(); - if (! $valid) { + if (!$valid) { throw new Exception(Exception::GENERAL_SMTP_DISABLED); } @@ -1670,10 +1712,11 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1681,11 +1724,11 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['sms.'.$type.'-'.$locale] ?? null; + $template = $templates['sms.' . $type . '-' . $locale] ?? null; if (is_null($template)) { $template = [ - 'message' => Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl')->render(), + 'message' => Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl')->render(), ]; } @@ -1707,10 +1750,11 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1718,11 +1762,11 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['email.'.$type.'-'.$locale] ?? null; + $template = $templates['email.' . $type . '-' . $locale] ?? null; $localeObj = new Locale($locale); if (is_null($template)) { - $message = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); $message = $message ->setParam('{{hello}}', $localeObj->getText("emails.{$type}.hello")) ->setParam('{{name}}', '') @@ -1737,12 +1781,12 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->render(); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($localeObj->getText('emails.sender'), $project->getAttribute('name')); - $from = empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')) : $from; + $from = empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')) : $from; $template = [ 'message' => $message, - 'subject' => $localeObj->getText('emails.'.$type.'.subject'), + 'subject' => $localeObj->getText('emails.' . $type . '.subject'), 'senderEmail' => App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', ''), - 'senderName' => $from, + 'senderName' => $from ]; } @@ -1764,11 +1808,12 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('message', '', new Text(0), 'Template message') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1776,8 +1821,8 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $templates['sms.'.$type.'-'.$locale] = [ - 'message' => $message, + $templates['sms.' . $type . '-' . $locale] = [ + 'message' => $message ]; $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); @@ -1801,7 +1846,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('senderName', '', new Text(255), 'Name of the email sender') ->param('senderEmail', '', new Email(), 'Email of the sender') ->param('subject', '', new Text(255), 'Email Subject') @@ -1810,6 +1855,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, string $senderName, string $senderEmail, string $subject, string $message, string $replyTo, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1817,12 +1863,12 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $templates['email.'.$type.'-'.$locale] = [ + $templates['email.' . $type . '-' . $locale] = [ 'senderName' => $senderName, 'senderEmail' => $senderEmail, 'subject' => $subject, 'replyTo' => $replyTo, - 'message' => $message, + 'message' => $message ]; $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); @@ -1834,7 +1880,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') 'senderEmail' => $senderEmail, 'subject' => $subject, 'replyTo' => $replyTo, - 'message' => $message, + 'message' => $message ]), Response::MODEL_EMAIL_TEMPLATE); }); @@ -1850,10 +1896,11 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1861,20 +1908,20 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['sms.'.$type.'-'.$locale] ?? null; + $template = $templates['sms.' . $type . '-' . $locale] ?? null; if (is_null($template)) { throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION); } - unset($template['sms.'.$type.'-'.$locale]); + unset($template['sms.' . $type . '-' . $locale]); $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, 'locale' => $locale, - 'message' => $template['message'], + 'message' => $template['message'] ]), Response::MODEL_SMS_TEMPLATE); }); @@ -1890,10 +1937,11 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1901,13 +1949,13 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['email.'.$type.'-'.$locale] ?? null; + $template = $templates['email.' . $type . '-' . $locale] ?? null; if (is_null($template)) { throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION); } - unset($templates['email.'.$type.'-'.$locale]); + unset($templates['email.' . $type . '-' . $locale]); $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); @@ -1918,6 +1966,6 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') 'senderEmail' => $template['senderEmail'], 'subject' => $template['subject'], 'replyTo' => $template['replyTo'], - 'message' => $template['message'], + 'message' => $template['message'] ]), Response::MODEL_EMAIL_TEMPLATE); }); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 3206e2231f..c34515b5e1 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -4,27 +4,28 @@ use Appwrite\Auth\Auth; use Appwrite\ClamAV\Network; use Appwrite\Event\Delete; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; -use Appwrite\OpenSSL\OpenSSL; use Appwrite\Utopia\Database\Validator\CustomId; -use Appwrite\Utopia\Database\Validator\Queries\Buckets; -use Appwrite\Utopia\Database\Validator\Queries\Files; +use Appwrite\OpenSSL\OpenSSL; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization as AuthorizationException; +use Utopia\Database\DateTime; use Utopia\Database\Exception\Duplicate; +use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; use Utopia\Database\Query; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; +use Appwrite\Extend\Exception; +use Appwrite\Utopia\Database\Validator\Queries\Buckets; +use Appwrite\Utopia\Database\Validator\Queries\Files; use Utopia\Image\Image; use Utopia\Storage\Compression\Algorithms\GZIP; use Utopia\Storage\Compression\Algorithms\Zstd; @@ -34,13 +35,14 @@ use Utopia\Storage\Validator\File; use Utopia\Storage\Validator\FileExt; use Utopia\Storage\Validator\FileSize; use Utopia\Storage\Validator\Upload; -use Utopia\Swoole\Request; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; use Utopia\Validator\HexColor; use Utopia\Validator\Range; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; +use Utopia\DSN\DSN; +use Utopia\Swoole\Request; App::post('/v1/storage/buckets') ->desc('Create bucket') @@ -61,15 +63,16 @@ App::post('/v1/storage/buckets') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true) - ->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is '.Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0).'. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) - ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' extensions are allowed, each 64 characters long.', true) - ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of '.COMPRESSION_TYPE_NONE.', ['.COMPRESSION_TYPE_GZIP.'](https://en.wikipedia.org/wiki/Gzip), or ['.COMPRESSION_TYPE_ZSTD.'](https://en.wikipedia.org/wiki/Zstd), For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' compression is skipped even if it\'s enabled', true) - ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' encryption is skipped even if it\'s enabled', true) - ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above '.Storage::human(APP_LIMIT_ANTIVIRUS, 0).' AntiVirus scanning is skipped even if it\'s enabled', true) + ->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) + ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) + ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) + ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('events') ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) { + $bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId; // Map aggregate permissions into the multiple permissions they represent. @@ -94,7 +97,7 @@ App::post('/v1/storage/buckets') 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '', + 'format' => $attribute['format'] ?? '' ]); } @@ -125,13 +128,14 @@ App::post('/v1/storage/buckets') $bucket = $dbForProject->getDocument('buckets', $bucketId); - $dbForProject->createCollection('bucket_'.$bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); + $dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); } catch (Duplicate) { throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS); } $events - ->setParam('bucketId', $bucket->getId()); + ->setParam('bucketId', $bucket->getId()) + ; $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -149,14 +153,15 @@ App::get('/v1/storage/buckets') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET_LIST) - ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -198,6 +203,7 @@ App::get('/v1/storage/buckets/:bucketId') ->inject('response') ->inject('dbForProject') ->action(function (string $bucketId, Response $response, Database $dbForProject) { + $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { @@ -226,11 +232,11 @@ App::put('/v1/storage/buckets/:bucketId') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true) - ->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is '.Storage::human((int) App::getEnv('_APP_STORAGE_LIMIT', 0), 0).'. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) - ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' extensions are allowed, each 64 characters long.', true) - ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of '.COMPRESSION_TYPE_NONE.', ['.COMPRESSION_TYPE_GZIP.'](https://en.wikipedia.org/wiki/Gzip), or ['.COMPRESSION_TYPE_ZSTD.'](https://en.wikipedia.org/wiki/Zstd), For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' compression is skipped even if it\'s enabled', true) - ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above '.Storage::human(APP_STORAGE_READ_BUFFER, 0).' encryption is skipped even if it\'s enabled', true) - ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above '.Storage::human(APP_LIMIT_ANTIVIRUS, 0).' AntiVirus scanning is skipped even if it\'s enabled', true) + ->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](/docs/environment-variables#storage)', true) + ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) + ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) + ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('events') @@ -265,10 +271,11 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('encryption', $encryption) ->setAttribute('compression', $compression) ->setAttribute('antivirus', $antivirus)); - $dbForProject->updateCollection('bucket_'.$bucket->getInternalId(), $permissions, $fileSecurity); + $dbForProject->updateCollection('bucket_' . $bucket->getInternalId(), $permissions, $fileSecurity); $events - ->setParam('bucketId', $bucket->getId()); + ->setParam('bucketId', $bucket->getId()) + ; $response->dynamic($bucket, Response::MODEL_BUCKET); }); @@ -298,7 +305,7 @@ App::delete('/v1/storage/buckets/:bucketId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (! $dbForProject->deleteDocument('buckets', $bucketId)) { + if (!$dbForProject->deleteDocument('buckets', $bucketId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove bucket from DB'); } @@ -308,7 +315,8 @@ App::delete('/v1/storage/buckets/:bucketId') $events ->setParam('bucketId', $bucket->getId()) - ->setPayload($response->output($bucket, Response::MODEL_BUCKET)); + ->setPayload($response->output($bucket, Response::MODEL_BUCKET)) + ; $response->noContent(); }); @@ -346,14 +354,15 @@ App::post('/v1/storage/buckets/:bucketId/files') ->inject('deviceFiles') ->inject('deviceLocal') ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $validator = new Authorization(Database::PERMISSION_CREATE); - if (! $validator->isValid($bucket->getCreate())) { + if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -369,7 +378,7 @@ App::post('/v1/storage/buckets/:bucketId/files') // Add permissions for current the user if none were provided. if (\is_null($permissions)) { $permissions = []; - if (! empty($user->getId())) { + if (!empty($user->getId())) { foreach ($allowedPermissions as $permission) { $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); } @@ -378,7 +387,7 @@ App::post('/v1/storage/buckets/:bucketId/files') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles)) { + if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -390,8 +399,8 @@ App::post('/v1/storage/buckets/:bucketId/files') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (! Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } } @@ -402,6 +411,7 @@ App::post('/v1/storage/buckets/:bucketId/files') throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Maximum bucket file size is larger than _APP_STORAGE_LIMIT'); } + $file = $request->getFiles('file'); // GraphQL multipart spec adds files with index keys @@ -423,7 +433,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $chunk = 1; $chunks = 1; - if (! empty($contentRange)) { + if (!empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); @@ -434,7 +444,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } $idValidator = new UID(); - if (! $idValidator->isValid($request->getHeader('x-appwrite-id'))) { + if (!$idValidator->isValid($request->getHeader('x-appwrite-id'))) { throw new Exception(Exception::STORAGE_INVALID_APPWRITE_ID); } @@ -455,30 +465,30 @@ App::post('/v1/storage/buckets/:bucketId/files') // Check if file type is allowed $allowedFileExtensions = $bucket->getAttribute('allowedFileExtensions', []); $fileExt = new FileExt($allowedFileExtensions); - if (! empty($allowedFileExtensions) && ! $fileExt->isValid($fileName)) { + if (!empty($allowedFileExtensions) && !$fileExt->isValid($fileName)) { throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, 'File extension not allowed'); } // Check if file size is exceeding allowed limit $fileSizeValidator = new FileSize($maximumFileSize); - if (! $fileSizeValidator->isValid($fileSize)) { + if (!$fileSizeValidator->isValid($fileSize)) { throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE, 'File size not allowed'); } $upload = new Upload(); - if (! $upload->isValid($fileTmpName)) { + if (!$upload->isValid($fileTmpName)) { throw new Exception(Exception::STORAGE_INVALID_FILE); } // Save to storage $fileSize ??= $deviceLocal->getFileSize($fileTmpName); - $path = $deviceFiles->getPath($fileId.'.'.\pathinfo($fileName, PATHINFO_EXTENSION)); - $path = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot().DIRECTORY_SEPARATOR.$bucket->getId(), $path); // Add bucket id to path after root + $path = $deviceFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); + $path = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root - $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); $metadata = ['content_type' => $deviceLocal->getFileMimeType($fileTmpName)]; - if (! $file->isEmpty()) { + if (!$file->isEmpty()) { $chunks = $file->getAttribute('chunksTotal', 1); $metadata = $file->getAttribute('metadata', []); if ($chunk === -1) { @@ -498,7 +508,7 @@ App::post('/v1/storage/buckets/:bucketId/files') (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310) ); - if (! $antivirus->fileScan($path)) { + if (!$antivirus->fileScan($path)) { $deviceFiles->delete($path); throw new Exception(Exception::STORAGE_INVALID_FILE); } @@ -532,8 +542,8 @@ App::post('/v1/storage/buckets/:bucketId/files') $data = OpenSSL::encrypt($data, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag); } - if (! empty($data)) { - if (! $deviceFiles->write($path, $data, $mimeType)) { + if (!empty($data)) { + if (!$deviceFiles->write($path, $data, $mimeType)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to save file'); } } @@ -577,7 +587,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_'.$bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); } else { $file = $file ->setAttribute('$permissions', $permissions) @@ -592,7 +602,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ->setAttribute('metadata', $metadata) ->setAttribute('chunksUploaded', $chunksUploaded); - $file = $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); } } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); @@ -623,13 +633,13 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_'.$bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); } else { $file = $file ->setAttribute('chunksUploaded', $chunksUploaded) ->setAttribute('metadata', $metadata); - $file = $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); } } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); @@ -643,7 +653,8 @@ App::post('/v1/storage/buckets/:bucketId/files') $events ->setParam('bucketId', $bucket->getId()) ->setParam('fileId', $file->getId()) - ->setContext('bucket', $bucket); + ->setContext('bucket', $bucket) + ; $metadata = null; // was causing leaks as it was passed by reference @@ -665,28 +676,29 @@ App::get('/v1/storage/buckets/:bucketId/files') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_FILE_LIST) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).') - ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('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) ->inject('response') ->inject('dbForProject') ->inject('mode') ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -697,10 +709,10 @@ App::get('/v1/storage/buckets/:bucketId/files') /** @var Query $cursor */ $fileId = $cursor->getValue(); - if ($fileSecurity && ! $valid) { - $cursorDocument = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + if ($fileSecurity && !$valid) { + $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -712,12 +724,12 @@ App::get('/v1/storage/buckets/:bucketId/files') $filterQueries = Query::groupByType($queries)['filters']; - if ($fileSecurity && ! $valid) { - $files = $dbForProject->find('bucket_'.$bucket->getInternalId(), $queries); - $total = $dbForProject->count('bucket_'.$bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + if ($fileSecurity && !$valid) { + $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); + $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_'.$bucket->getInternalId(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_'.$bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); + $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); } $response->dynamic(new Document([ @@ -744,23 +756,24 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('dbForProject') ->inject('mode') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && ! $valid) { - $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + if ($fileSecurity && !$valid) { + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -789,7 +802,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->param('fileId', '', new UID(), 'File ID') ->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true) ->param('height', 0, new Range(0, 4000), 'Resize preview image height, Pass an integer between 0 to 4000.', true) - ->param('gravity', Image::GRAVITY_CENTER, new WhiteList(Image::getGravityTypes()), 'Image crop gravity. Can be one of '.implode(',', Image::getGravityTypes()), true) + ->param('gravity', Image::GRAVITY_CENTER, new WhiteList(Image::getGravityTypes()), 'Image crop gravity. Can be one of ' . implode(",", Image::getGravityTypes()), true) ->param('quality', 100, new Range(0, 100), 'Preview image quality. Pass an integer between 0 to 100. Defaults to 100.', true) ->param('borderWidth', 0, new Range(0, 100), 'Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.', true) ->param('borderColor', '', new HexColor(), 'Preview image border color. Use a valid HEX color, no # is needed for prefix.', true) @@ -806,20 +819,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->inject('deviceFiles') ->inject('deviceLocal') ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceFiles, Device $deviceLocal) { - if (! \extension_loaded('imagick')) { + + if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -831,10 +845,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $outputs = Config::getParam('storage-outputs'); $fileLogos = Config::getParam('storage-logos'); - if ($fileSecurity && ! $valid) { - $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + if ($fileSecurity && !$valid) { + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -846,8 +860,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $algorithm = $file->getAttribute('algorithm', 'none'); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); - if (! \in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { - if (! \in_array($mime, $inputs)) { + if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { + if (!\in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { // it was an image but the file size exceeded the limit @@ -861,7 +875,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $deviceFiles = $deviceLocal; } - if (! $deviceFiles->exists($path)) { + if (!$deviceFiles->exists($path)) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -871,13 +885,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $output = empty($type) ? (array_search($mime, $outputs) ?? 'jpg') : $type; } + $source = $deviceFiles->read($path); - if (! empty($cipher)) { // Decrypt + if (!empty($cipher)) { // Decrypt $source = OpenSSL::decrypt( $source, $file->getAttribute('openSSLCipher'), - App::getEnv('_APP_OPENSSL_KEY_V'.$file->getAttribute('openSSLVersion')), + App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')), 0, \hex2bin($file->getAttribute('openSSLIV')), \hex2bin($file->getAttribute('openSSLTag')) @@ -899,23 +914,23 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $image->crop((int) $width, (int) $height, $gravity); - if (! empty($opacity) || $opacity === 0) { + if (!empty($opacity) || $opacity === 0) { $image->setOpacity($opacity); } - if (! empty($background)) { - $image->setBackground('#'.$background); + if (!empty($background)) { + $image->setBackground('#' . $background); } - if (! empty($borderWidth)) { - $image->setBorder($borderWidth, '#'.$borderColor); + if (!empty($borderWidth)) { + $image->setBorder($borderWidth, '#' . $borderColor); } - if (! empty($borderRadius)) { + if (!empty($borderRadius)) { $image->setBorderRadius($borderRadius); } - if (! empty($rotation)) { + if (!empty($rotation)) { $image->setRotation(($rotation + 360) % 360); } @@ -924,9 +939,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30).' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT') ->setContentType($contentType) - ->file($data); + ->file($data) + ; unset($image); }); @@ -951,23 +967,24 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->inject('mode') ->inject('deviceFiles') ->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceFiles) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && ! $valid) { - $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + if ($fileSecurity && !$valid) { + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -976,20 +993,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $path = $file->getAttribute('path', ''); - if (! $deviceFiles->exists($path)) { - throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in '.$path); + if (!$deviceFiles->exists($path)) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } $response ->setContentType($file->getAttribute('mimeType')) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="'.$file->getAttribute('name', '').'"'); + ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') + ; $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); - if (! empty($rangeHeader)) { + if (!empty($rangeHeader)) { $start = $request->getRangeStart(); $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); @@ -1004,18 +1022,18 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $response ->addHeader('Accept-Ranges', 'bytes') - ->addHeader('Content-Range', 'bytes '.$start.'-'.$end.'/'.$size) + ->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size) ->addHeader('Content-Length', $end - $start + 1) ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } $source = ''; - if (! empty($file->getAttribute('openSSLCipher'))) { // Decrypt + if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceFiles->read($path); $source = OpenSSL::decrypt( $source, $file->getAttribute('openSSLCipher'), - App::getEnv('_APP_OPENSSL_KEY_V'.$file->getAttribute('openSSLVersion')), + App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')), 0, \hex2bin($file->getAttribute('openSSLIV')), \hex2bin($file->getAttribute('openSSLTag')) @@ -1039,14 +1057,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') break; } - if (! empty($source)) { - if (! empty($rangeHeader)) { + if (!empty($source)) { + if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); } - if (! empty($rangeHeader)) { + if (!empty($rangeHeader)) { $response->send($deviceFiles->read($path, $start, ($end - $start + 1))); } @@ -1087,23 +1105,24 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->inject('mode') ->inject('deviceFiles') ->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceFiles) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - if ($fileSecurity && ! $valid) { - $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + if ($fileSecurity && !$valid) { + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -1114,8 +1133,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $path = $file->getAttribute('path', ''); - if (! $deviceFiles->exists($path)) { - throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in '.$path); + if (!$deviceFiles->exists($path)) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } $contentType = 'text/plain'; @@ -1128,14 +1147,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setContentType($contentType) ->addHeader('Content-Security-Policy', 'script-src none;') ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="'.$file->getAttribute('name', '').'"') - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache - ->addHeader('X-Peak', \memory_get_peak_usage()); + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('X-Peak', \memory_get_peak_usage()) + ; $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); - if (! empty($rangeHeader)) { + if (!empty($rangeHeader)) { $start = $request->getRangeStart(); $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); @@ -1156,12 +1176,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } $source = ''; - if (! empty($file->getAttribute('openSSLCipher'))) { // Decrypt + if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceFiles->read($path); $source = OpenSSL::decrypt( $source, $file->getAttribute('openSSLCipher'), - App::getEnv('_APP_OPENSSL_KEY_V'.$file->getAttribute('openSSLVersion')), + App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')), 0, \hex2bin($file->getAttribute('openSSLIV')), \hex2bin($file->getAttribute('openSSLTag')) @@ -1185,14 +1205,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') break; } - if (! empty($source)) { - if (! empty($rangeHeader)) { + if (!empty($source)) { + if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); } - if (! empty($rangeHeader)) { + if (!empty($rangeHeader)) { $response->send($deviceFiles->read($path, $start, ($end - $start + 1))); } @@ -1242,21 +1262,22 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('mode') ->inject('events') ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $events) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttributes('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_UPDATE); $valid = $validator->isValid($bucket->getUpdate()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1271,7 +1292,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (! Auth::isAppUser($roles) && ! Auth::isPrivilegedUser($roles) && ! \is_null($permissions)) { + if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -1283,8 +1304,8 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (! Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: ('.\implode(', ', $roles).')'); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } } @@ -1296,24 +1317,25 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $file->setAttribute('$permissions', $permissions); - if (! is_null($name)) { + if (!is_null($name)) { $file->setAttribute('name', $name); } - if ($fileSecurity && ! $valid) { + if ($fileSecurity && !$valid) { try { - $file = $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_'.$bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } $events ->setParam('bucketId', $bucket->getId()) ->setParam('fileId', $file->getId()) - ->setContext('bucket', $bucket); + ->setContext('bucket', $bucket) + ; $response->dynamic($file, Response::MODEL_FILE); }); @@ -1346,26 +1368,26 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $events, string $mode, Device $deviceFiles, Delete $deletes) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttributes('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_DELETE); $valid = $validator->isValid($bucket->getDelete()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } // Make sure we don't delete the file before the document permission check occurs - if ($fileSecurity && ! $valid && ! $validator->isValid($file->getDelete())) { + if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1382,19 +1404,20 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') if ($deviceDeleted) { $deletes ->setType(DELETE_TYPE_CACHE_BY_RESOURCE) - ->setResource('file/'.$fileId); + ->setResource('file/' . $fileId) + ; - if ($fileSecurity && ! $valid) { + if ($fileSecurity && !$valid) { try { - $deleted = $dbForProject->deleteDocument('bucket_'.$bucket->getInternalId(), $fileId); + $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $deleted = Authorization::skip(fn() => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); } - if (! $deleted) { + if (!$deleted) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove file from DB'); } } else { @@ -1405,7 +1428,8 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->setParam('bucketId', $bucket->getId()) ->setParam('fileId', $file->getId()) ->setContext('bucket', $bucket) - ->setPayload($response->output($file, Response::MODEL_FILE)); + ->setPayload($response->output($file, Response::MODEL_FILE)) + ; $response->noContent(); }); @@ -1424,6 +1448,7 @@ App::get('/v1/storage/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $range, Response $response, Database $dbForProject) { + $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -1493,6 +1518,7 @@ App::get('/v1/storage/:bucketId/usage') ->inject('response') ->inject('dbForProject') ->action(function (string $bucketId, string $range, Response $response, Database $dbForProject) { + $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index e50378f4b6..e03e481d7c 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -9,10 +9,14 @@ use Appwrite\Event\Mail; use Appwrite\Event\Phone as EventPhone; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; +use Utopia\Validator\Host; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; +use Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Memberships; use Appwrite\Utopia\Database\Validator\Queries\Teams; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -20,24 +24,20 @@ use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; use Utopia\Database\Query; +use Utopia\Database\DateTime; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; -use Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; -use Utopia\Validator\Host; use Utopia\Validator\Text; App::post('/v1/teams') @@ -56,19 +56,20 @@ App::post('/v1/teams') ->label('sdk.response.model', Response::MODEL_TEAM) ->param('teamId', '', new CustomId(), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') - ->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 32 characters long.', true) + ->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true) ->inject('response') ->inject('user') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $events) { + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); $teamId = $teamId == 'unique()' ? ID::unique() : $teamId; try { - $team = Authorization::skip(fn () => $dbForProject->createDocument('teams', new Document([ + $team = Authorization::skip(fn() => $dbForProject->createDocument('teams', new Document([ '$id' => $teamId, '$permissions' => [ Permission::read(Role::team($teamId)), @@ -84,8 +85,8 @@ App::post('/v1/teams') throw new Exception(Exception::TEAM_ALREADY_EXISTS); } - if (! $isPrivilegedUser && ! $isAppUser) { // Don't add user on server mode - if (! \in_array('owner', $roles)) { + if (!$isPrivilegedUser && !$isAppUser) { // Don't add user on server mode + if (!\in_array('owner', $roles)) { $roles[] = 'owner'; } @@ -109,7 +110,7 @@ App::post('/v1/teams') 'joined' => DateTime::now(), 'confirm' => true, 'secret' => '', - 'search' => implode(' ', [$membershipId, $user->getId()]), + 'search' => implode(' ', [$membershipId, $user->getId()]) ]); $membership = $dbForProject->createDocument('memberships', $membership); @@ -118,7 +119,7 @@ App::post('/v1/teams') $events->setParam('teamId', $team->getId()); - if (! empty($user->getId())) { + if (!empty($user->getId())) { $events->setParam('userId', $user->getId()); } @@ -139,14 +140,15 @@ App::get('/v1/teams') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TEAM_LIST) ->label('sdk.offline.model', '/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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -193,6 +195,7 @@ App::get('/v1/teams/:teamId') ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, Response $response, Database $dbForProject) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -218,6 +221,7 @@ App::get('/v1/teams/:teamId/prefs') ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, Response $response, Database $dbForProject) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -252,6 +256,7 @@ App::put('/v1/teams/:teamId') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $name, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $events) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -293,6 +298,7 @@ App::put('/v1/teams/:teamId/prefs') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, array $prefs, Response $response, Database $dbForProject, Event $events) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -325,13 +331,14 @@ App::delete('/v1/teams/:teamId') ->inject('events') ->inject('deletes') ->action(function (string $teamId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); } - if (! $dbForProject->deleteDocument('teams', $teamId)) { + if (!$dbForProject->deleteDocument('teams', $teamId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove team from DB'); } @@ -341,7 +348,8 @@ App::delete('/v1/teams/:teamId') $events ->setParam('teamId', $team->getId()) - ->setPayload($response->output($team, Response::MODEL_TEAM)); + ->setPayload($response->output($team, Response::MODEL_TEAM)) + ; $response->noContent(); }); @@ -367,8 +375,8 @@ App::post('/v1/teams/:teamId/memberships') ->param('email', '', new Email(), 'Email of the new team member.', true) ->param('userId', '', new UID(), 'ID of the user to be added to a team.', true) ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) - ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 32 characters long.') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation 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, ['clients']) // TODO add our own built-in confirm page + ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') + ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation 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, ['clients']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) ->inject('response') ->inject('project') @@ -379,13 +387,14 @@ App::post('/v1/teams/:teamId/memberships') ->inject('messaging') ->inject('events') ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, EventPhone $messaging, Event $events) { + if (empty($userId) && empty($email) && empty($phone)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'At least one of userId, email, or phone is required'); } $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); - if (! $isPrivilegedUser && ! $isAppUser && empty(App::getEnv('_APP_SMTP_HOST'))) { + if (!$isPrivilegedUser && !$isAppUser && empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED); } @@ -396,28 +405,28 @@ App::post('/v1/teams/:teamId/memberships') if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); } - if (! empty($userId)) { + if (!empty($userId)) { $invitee = $dbForProject->getDocument('users', $userId); if ($invitee->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND, 'User with given userId doesn\'t exist.', 404); } - if (! empty($email) && $invitee->getAttribute('email', '') !== $email) { + if (!empty($email) && $invitee->getAttribute('email', '') !== $email) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given userId and email doesn\'t match', 409); } - if (! empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { + if (!empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given userId and phone doesn\'t match', 409); } $email = $invitee->getAttribute('email', ''); $phone = $invitee->getAttribute('phone', ''); $name = empty($name) ? $invitee->getAttribute('name', '') : $name; - } elseif (! empty($email)) { + } elseif (!empty($email)) { $invitee = $dbForProject->findOne('users', [Query::equal('email', [$email])]); // Get user by email address - if (! empty($invitee) && ! empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { + if (!empty($invitee) && !empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given email and phone doesn\'t match', 409); } - } elseif (! empty($phone)) { + } elseif (!empty($phone)) { $invitee = $dbForProject->findOne('users', [Query::equal('phone', [$phone])]); - if (! empty($invitee) && ! empty($email) && $invitee->getAttribute('email', '') !== $email) { + if (!empty($invitee) && !empty($email) && $invitee->getAttribute('email', '') !== $email) { throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given phone and email doesn\'t match', 409); } } @@ -437,13 +446,13 @@ App::post('/v1/teams/:teamId/memberships') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } try { $userId = ID::unique(); - $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([ + $invitee = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ Permission::read(Role::any()), @@ -471,16 +480,16 @@ App::post('/v1/teams/:teamId/memberships') 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]), + 'search' => implode(' ', [$userId, $email, $name]) ]))); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = Authorization::isRole('team:'.$team->getId().'/owner'); + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); - if (! $isOwner && ! $isPrivilegedUser && ! $isAppUser) { // Not owner, not admin, not app (server) + if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to send invitations for this team'); } @@ -505,17 +514,17 @@ App::post('/v1/teams/:teamId/memberships') 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, 'confirm' => ($isPrivilegedUser || $isAppUser), 'secret' => Auth::hash($secret), - 'search' => implode(' ', [$membershipId, $invitee->getId()]), + 'search' => implode(' ', [$membershipId, $invitee->getId()]) ]); if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership try { - $membership = Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)); + $membership = Authorization::skip(fn() => $dbForProject->createDocument('memberships', $membership)); } catch (Duplicate $th) { throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); } $team->setAttribute('total', $team->getAttribute('total', 0) + 1); - $team = Authorization::skip(fn () => $dbForProject->updateDocument('teams', $team->getId(), $team)); + $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); $dbForProject->deleteCachedDocument('users', $invitee->getId()); } else { @@ -528,16 +537,16 @@ App::post('/v1/teams/:teamId/memberships') $url = Template::parseURL($url); $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); $url = Template::unParseURL($url); - if (! empty($email)) { + if (!empty($email)) { $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); - $body = Template::fromFile(__DIR__.'/../../config/locale/templates/email-base.tpl'); - $subject = \sprintf($locale->getText('emails.invitation.subject'), $team->getAttribute('name'), $projectName); + $body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl'); + $subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName); $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; - $customTemplate = $project->getAttribute('templates', [])['email.invitation-'.$locale->default] ?? []; - if ($smtpEnabled && ! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message']; $subject = $customTemplate['subject']; $from = $customTemplate['senderName']; @@ -548,13 +557,13 @@ App::post('/v1/teams/:teamId/memberships') $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText('emails.invitation.hello')) + ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) ->setParam('{{name}}', $user->getAttribute('name')) - ->setParam('{{body}}', $locale->getText('emails.invitation.body')) + ->setParam('{{body}}', $locale->getText("emails.invitation.body")) ->setParam('{{redirect}}', $url) - ->setParam('{{footer}}', $locale->getText('emails.invitation.footer')) - ->setParam('{{thanks}}', $locale->getText('emails.invitation.thanks')) - ->setParam('{{signature}}', $locale->getText('emails.invitation.signature')) + ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")) ->setParam('{{project}}', $projectName) ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -569,12 +578,13 @@ App::post('/v1/teams/:teamId/memberships') ->setFrom($from) ->setRecipient($invitee->getAttribute('email')) ->setName($invitee->getAttribute('name')) - ->trigger(); - } elseif (! empty($phone)) { - $message = Template::fromFile(__DIR__.'/../../config/locale/templates/sms-base.tpl'); + ->trigger() + ; + } elseif (!empty($phone)) { + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.invitation-'.$locale->default] ?? []; - if (! empty($customTemplate)) { + $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; + if (!empty($customTemplate)) { $message = $customTemplate['message']; } @@ -590,7 +600,8 @@ App::post('/v1/teams/:teamId/memberships') $events ->setParam('teamId', $team->getId()) - ->setParam('membershipId', $membership->getId()); + ->setParam('membershipId', $membership->getId()) + ; $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -616,11 +627,12 @@ App::get('/v1/teams/:teamId/memberships') ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) ->label('sdk.offline.model', '/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('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) ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, array $queries, string $search, Response $response, Database $dbForProject) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -629,7 +641,7 @@ App::get('/v1/teams/:teamId/memberships') $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -664,7 +676,7 @@ App::get('/v1/teams/:teamId/memberships') max: APP_LIMIT_COUNT ); - $memberships = array_filter($memberships, fn (Document $membership) => ! empty($membership->getAttribute('userId'))); + $memberships = array_filter($memberships, fn(Document $membership) => !empty($membership->getAttribute('userId'))); $memberships = array_map(function ($membership) use ($dbForProject, $team) { $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); @@ -672,7 +684,8 @@ App::get('/v1/teams/:teamId/memberships') $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')); + ->setAttribute('userEmail', $user->getAttribute('email')) + ; return $membership; }, $memberships); @@ -701,6 +714,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('dbForProject') ->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -718,7 +732,8 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')); + ->setAttribute('userEmail', $user->getAttribute('email')) + ; $response->dynamic($membership, Response::MODEL_MEMBERSHIP); }); @@ -739,13 +754,14 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') - ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of '.APP_LIMIT_ARRAY_PARAMS_SIZE.' roles are allowed, each 32 characters long.') + ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') ->inject('request') ->inject('response') ->inject('user') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $events) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -763,9 +779,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:'.$team->getId().'/owner'); + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); - if (! $isOwner && ! $isPrivilegedUser && ! $isAppUser) { // Not owner, not admin, not app (server) + if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles'); } @@ -832,7 +848,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } - $team = Authorization::skip(fn () => $dbForProject->getDocument('teams', $teamId)); + $team = Authorization::skip(fn() => $dbForProject->getDocument('teams', $teamId)); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -843,7 +859,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } if ($userId !== $membership->getAttribute('userId')) { - throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user ('.$user->getAttribute('email').')'); + throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } if ($user->isEmpty()) { @@ -851,7 +867,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } if ($membership->getAttribute('userId') !== $user->getId()) { - throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user ('.$user->getAttribute('email').')'); + throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } if ($membership->getAttribute('confirm') === true) { @@ -860,9 +876,10 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $membership // Attach user to team ->setAttribute('joined', DateTime::now()) - ->setAttribute('confirm', true); + ->setAttribute('confirm', true) + ; - Authorization::skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); + Authorization::skip(fn() => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); // Log user in @@ -900,20 +917,23 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->deleteCachedDocument('users', $user->getId()); - $team = Authorization::skip(fn () => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); + $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); $events ->setParam('teamId', $team->getId()) - ->setParam('membershipId', $membership->getId()); + ->setParam('membershipId', $membership->getId()) + ; - if (! Config::getParam('domainVerification')) { + if (!Config::getParam('domainVerification')) { $response - ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); + ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) + ; } $response - ->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')); + ->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')) + ; $response->dynamic( $membership @@ -943,6 +963,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('dbForProject') ->inject('events') ->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, Event $events) { + $membership = $dbForProject->getDocument('memberships', $membershipId); if ($membership->isEmpty()) { @@ -977,13 +998,14 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') if ($membership->getAttribute('confirm')) { // Count only confirmed members $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)); - Authorization::skip(fn () => $dbForProject->updateDocument('teams', $team->getId(), $team)); + Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); } $events ->setParam('teamId', $team->getId()) ->setParam('membershipId', $membership->getId()) - ->setPayload($response->output($membership, Response::MODEL_MEMBERSHIP)); + ->setPayload($response->output($membership, Response::MODEL_MEMBERSHIP)) + ; $response->noContent(); }); @@ -1006,6 +1028,7 @@ App::get('/v1/teams/:teamId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1018,13 +1041,13 @@ App::get('/v1/teams/:teamId/logs') $offset = $grouped['offset'] ?? 0; $audit = new Audit($dbForProject); - $resource = 'team/'.$team->getId(); + $resource = 'team/' . $team->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -1052,14 +1075,14 @@ App::get('/v1/teams/:teamId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index f868bdd69e..cf94135351 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2,43 +2,43 @@ use Appwrite\Auth\Auth; use Appwrite\Auth\Validator\Password; -use Appwrite\Auth\Validator\PasswordDictionary; -use Appwrite\Auth\Validator\PasswordHistory; -use Appwrite\Auth\Validator\PersonalData; use Appwrite\Auth\Validator\Phone; use Appwrite\Detector\Detector; use Appwrite\Event\Delete; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Appwrite\Utopia\Database\Validator\CustomId; +use Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Database\Validator\Queries\Users; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Response; -use MaxMind\Db\Reader; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Locale\Locale; +use Appwrite\Extend\Exception; +use Utopia\Database\Document; +use Utopia\Database\DateTime; +use Utopia\Database\Exception\Duplicate; +use Utopia\Database\Validator\UID; +use Utopia\Database\Database; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; -use Utopia\Database\Validator\UID; -use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; -use Utopia\Validator\Boolean; -use Utopia\Validator\Integer; -use Utopia\Validator\Text; use Utopia\Validator\WhiteList; +use Utopia\Validator\Text; +use Utopia\Validator\Boolean; +use MaxMind\Db\Reader; +use Utopia\Validator\Integer; +use Appwrite\Auth\Validator\PasswordHistory; +use Appwrite\Auth\Validator\PasswordDictionary; +use Appwrite\Auth\Validator\PersonalData; /** TODO: Remove function when we move to using utopia/platform */ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $email, ?string $password, ?string $phone, string $name, Document $project, Database $dbForProject, Event $events): Document @@ -46,14 +46,14 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e $hashOptionsObject = (\is_string($hashOptions)) ? \json_decode($hashOptions, true) : $hashOptions; // Cast to JSON array $passwordHistory = $project->getAttribute('auths', [])['passwordHistory'] ?? 0; - if (! empty($email)) { + if (!empty($email)) { $email = \strtolower($email); // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } } @@ -65,12 +65,12 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($userId, $email, $name, $phone); - if (! $personalDataValidator->isValid($password)) { + if (!$personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } - $password = (! empty($password)) ? ($hash === 'plaintext' ? Auth::passwordHash($password, $hash, $hashOptionsObject) : $password) : null; + $password = (!empty($password)) ? ($hash === 'plaintext' ? Auth::passwordHash($password, $hash, $hashOptionsObject) : $password) : null; $user = $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ @@ -86,7 +86,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e 'labels' => [], 'password' => $password, 'passwordHistory' => is_null($password) && $passwordHistory === 0 ? [] : [$password], - 'passwordUpdate' => (! empty($password)) ? DateTime::now() : null, + 'passwordUpdate' => (!empty($password)) ? DateTime::now() : null, 'hash' => $hash === 'plaintext' ? Auth::DEFAULT_ALGO : $hash, 'hashOptions' => $hash === 'plaintext' ? Auth::DEFAULT_ALGO_OPTIONS : $hashOptionsObject + ['type' => $hash], 'registration' => DateTime::now(), @@ -96,7 +96,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e 'sessions' => null, 'tokens' => null, 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $phone, $name]), + 'search' => implode(' ', [$userId, $email, $phone, $name]) ])); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); @@ -131,6 +131,7 @@ App::post('/v1/users') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, ?string $email, ?string $phone, ?string $password, string $name, Response $response, Document $project, Database $dbForProject, Event $events) { + $user = createUser('plaintext', '{}', $userId, $email, $password, $phone, $name, $project, $dbForProject, $events); $response @@ -254,8 +255,8 @@ App::post('/v1/users/sha') ->action(function (string $userId, string $email, string $password, string $passwordVersion, string $name, Response $response, Document $project, Database $dbForProject, Event $events) { $options = '{}'; - if (! empty($passwordVersion)) { - $options = '{"version":"'.$passwordVersion.'"}'; + if (!empty($passwordVersion)) { + $options = '{"version":"' . $passwordVersion . '"}'; } $user = createUser('sha', $options, $userId, $email, $password, null, $name, $project, $dbForProject, $events); @@ -328,7 +329,7 @@ App::post('/v1/users/scrypt') 'costCpu' => $passwordCpu, 'costMemory' => $passwordMemory, 'costParallel' => $passwordParallel, - 'length' => $passwordLength, + 'length' => $passwordLength ]; $user = createUser('scrypt', \json_encode($options), $userId, $email, $password, null, $name, $project, $dbForProject, $events); @@ -364,7 +365,7 @@ App::post('/v1/users/scrypt-modified') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $email, string $password, string $passwordSalt, string $passwordSaltSeparator, string $passwordSignerKey, string $name, Response $response, Document $project, Database $dbForProject, Event $events) { - $user = createUser('scryptMod', '{"signerKey":"'.$passwordSignerKey.'","saltSeparator":"'.$passwordSaltSeparator.'","salt":"'.$passwordSalt.'"}', $userId, $email, $password, null, $name, $project, $dbForProject, $events); + $user = createUser('scryptMod', '{"signerKey":"' . $passwordSignerKey . '","saltSeparator":"' . $passwordSaltSeparator . '","salt":"' . $passwordSalt . '"}', $userId, $email, $password, null, $name, $project, $dbForProject, $events); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -405,7 +406,7 @@ App::post('/v1/users/:userId/targets') $target = $dbForProject->getDocument('targets', $targetId); - if (! $target->isEmpty()) { + if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); } @@ -413,7 +414,7 @@ App::post('/v1/users/:userId/targets') '$id' => $targetId, // TO DO: what permissions should be given when created a target. '$permissions' => [ - Permission::read(Role::any()), + Permission::read(Role::any()) ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), @@ -441,14 +442,15 @@ App::get('/v1/users') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_USER_LIST) - ->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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -490,6 +492,7 @@ App::get('/v1/users/:userId') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -514,6 +517,7 @@ App::get('/v1/users/:userId/prefs') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -541,6 +545,7 @@ App::get('/v1/users/:userId/targets/:targetId') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, string $targetId, Response $response, Database $dbForProject) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -572,6 +577,7 @@ App::get('/v1/users/:userId/sessions') ->inject('dbForProject') ->inject('locale') ->action(function (string $userId, Response $response, Database $dbForProject, Locale $locale) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -582,7 +588,8 @@ App::get('/v1/users/:userId/sessions') foreach ($sessions as $key => $session) { /** @var Document $session */ - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session->setAttribute('countryName', $countryName); $session->setAttribute('current', false); @@ -610,6 +617,7 @@ App::get('/v1/users/:userId/memberships') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -651,6 +659,7 @@ App::get('/v1/users/:userId/logs') ->inject('locale') ->inject('geodb') ->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -669,7 +678,7 @@ App::get('/v1/users/:userId/logs') $output = []; foreach ($logs as $i => &$log) { - $log['userAgent'] = (! empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) @@ -693,14 +702,14 @@ App::get('/v1/users/:userId/logs') 'clientEngineVersion' => $client['clientEngineVersion'], 'deviceName' => $device['deviceName'], 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -728,6 +737,7 @@ App::get('/v1/users/:userId/targets') ->inject('response') ->inject('dbForProject') ->action(function (string $userId, Response $response, Database $dbForProject) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -753,14 +763,15 @@ App::get('/v1/users/identities') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) - ->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('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) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + $queries = Query::parseQueries($queries); - if (! empty($search)) { + if (!empty($search)) { $queries[] = Query::search('search', $search); } @@ -808,6 +819,7 @@ App::patch('/v1/users/:userId/status') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $status, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -844,6 +856,7 @@ App::put('/v1/users/:userId/labels') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, array $labels, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -880,6 +893,7 @@ App::patch('/v1/users/:userId/verification') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $emailVerification, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -914,6 +928,7 @@ App::patch('/v1/users/:userId/verification/phone') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $phoneVerification, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -949,6 +964,7 @@ App::patch('/v1/users/:userId/name') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $name, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -986,6 +1002,7 @@ App::patch('/v1/users/:userId/password') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $password, Response $response, Document $project, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -994,7 +1011,7 @@ App::patch('/v1/users/:userId/password') if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) { $personalDataValidator = new PersonalData($userId, $user->getAttribute('email'), $user->getAttribute('name'), $user->getAttribute('phone')); - if (! $personalDataValidator->isValid($password)) { + if (!$personalDataValidator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_PERSONAL_DATA); } } @@ -1005,7 +1022,7 @@ App::patch('/v1/users/:userId/password') $history = $user->getAttribute('passwordHistory', []); if ($historyLimit > 0) { $validator = new PasswordHistory($history, $user->getAttribute('hash'), $user->getAttribute('hashOptions')); - if (! $validator->isValid($password)) { + if (!$validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -1048,6 +1065,7 @@ App::patch('/v1/users/:userId/email') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $email, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1061,13 +1079,15 @@ App::patch('/v1/users/:userId/email') Query::equal('providerEmail', [$email]), Query::notEqual('userId', $user->getId()), ]); - if ($identityWithMatchingEmail !== false && ! $identityWithMatchingEmail->isEmpty()) { + if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); } $user ->setAttribute('email', $email) - ->setAttribute('emailVerification', false); + ->setAttribute('emailVerification', false) + ; + try { $user = $dbForProject->updateDocument('users', $user->getId(), $user); @@ -1100,6 +1120,7 @@ App::patch('/v1/users/:userId/phone') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $number, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1108,7 +1129,8 @@ App::patch('/v1/users/:userId/phone') $user ->setAttribute('phone', $number) - ->setAttribute('phoneVerification', false); + ->setAttribute('phoneVerification', false) + ; try { $user = $dbForProject->updateDocument('users', $user->getId(), $user); @@ -1142,6 +1164,7 @@ App::patch('/v1/users/:userId/verification') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, bool $emailVerification, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1173,6 +1196,7 @@ App::patch('/v1/users/:userId/prefs') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, array $prefs, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1206,6 +1230,7 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1251,6 +1276,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, string $sessionId, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1292,6 +1318,7 @@ App::delete('/v1/users/:userId/sessions') ->inject('dbForProject') ->inject('events') ->action(function (string $userId, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1334,6 +1361,7 @@ App::delete('/v1/users/:userId') ->inject('events') ->inject('deletes') ->action(function (string $userId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1374,6 +1402,7 @@ App::delete('/v1/users/:userId/targets/:targetId') ->inject('dbForProject') ->inject('events') ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { + $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1420,6 +1449,7 @@ App::delete('/v1/users/identities/:identityId') ->inject('events') ->inject('deletes') ->action(function (string $identityId, Response $response, Database $dbForProject, Event $events, Delete $deletes) { + $identity = $dbForProject->getDocument('identities', $identityId); if ($identity->isEmpty()) { @@ -1446,6 +1476,7 @@ App::get('/v1/users/usage') ->inject('dbForProject') ->inject('register') ->action(function (string $range, Response $response, Database $dbForProject) { + $periods = Config::getParam('usage', []); $stats = $usage = []; $days = $periods[$range]; @@ -1478,22 +1509,22 @@ App::get('/v1/users/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; } + } $response->dynamic(new Document([ 'range' => $range, - 'usersTotal' => $usage[$metrics[0]], + 'usersTotal' => $usage[$metrics[0]], 'sessionsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_USERS); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index bbd3d45f31..e8d6bb225a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1,38 +1,38 @@ getHostname(); $domains = Config::getParam('domains', []); - if (! array_key_exists($domain, $domains)) { - $domain = new Domain(! empty($domain) ? $domain : ''); + if (!array_key_exists($domain, $domains)) { + $domain = new Domain(!empty($domain) ? $domain : ''); - if (empty($domain->get()) || ! $domain->isKnown() || $domain->isTest()) { + if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { $domains[$domain->get()] = false; - Console::warning($domain->get().' is not a publicly accessible domain. Skipping SSL certificate generation.'); + Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); } elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { Console::warning('Skipping SSL certificates generation on ACME challenge.'); } else { @@ -97,7 +97,7 @@ App::init() $envDomain = App::getEnv('_APP_DOMAIN', ''); $mainDomain = null; - if (! empty($envDomain) && $envDomain !== 'localhost') { + if (!empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; } else { $domainDocument = $dbForConsole->findOne('domains', [Query::orderAsc('_id')]); @@ -105,13 +105,13 @@ App::init() } if ($mainDomain !== $domain->get()) { - Console::warning($domain->get().' is not a main domain. Skipping SSL certificate generation.'); + Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); } else { $domainDocument = $dbForConsole->findOne('domains', [ - Query::equal('domain', [$domain->get()]), + Query::equal('domain', [$domain->get()]) ]); - if (! $domainDocument) { + if (!$domainDocument) { $domainDocument = new Document([ 'domain' => $domain->get(), 'tld' => $domain->getSuffix(), @@ -122,7 +122,7 @@ App::init() $domainDocument = $dbForConsole->createDocument('domains', $domainDocument); - Console::info('Issuing a TLS certificate for the main domain ('.$domain->get().') in a few seconds...'); + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); (new Certificate()) ->setDomain($domainDocument) @@ -145,7 +145,7 @@ App::init() throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } - if (! empty($route->getLabel('sdk.auth', [])) && $project->isEmpty() && ($route->getLabel('scope', '') !== 'public')) { + if (!empty($route->getLabel('sdk.auth', [])) && $project->isEmpty() && ($route->getLabel('scope', '') !== 'public')) { throw new AppwriteException(AppwriteException::PROJECT_UNKNOWN); } @@ -160,14 +160,14 @@ App::init() $refDomainOrigin = $origin; } - $refDomain = (! empty($protocol) ? $protocol : $request->getProtocol()).'://'.$refDomainOrigin.(! empty($port) ? ':'.$port : ''); + $refDomain = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $refDomainOrigin . (!empty($port) ? ':' . $port : ''); - $refDomain = (! $route->getLabel('origin', false)) // This route is publicly accessible + $refDomain = (!$route->getLabel('origin', false)) // This route is publicly accessible ? $refDomain - : (! empty($protocol) ? $protocol : $request->getProtocol()).'://'.$origin.(! empty($port) ? ':'.$port : ''); + : (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); $selfDomain = new Domain($request->getHostname()); - $endDomain = new Domain((string) $origin); + $endDomain = new Domain((string)$origin); Config::setParam( 'domainVerification', @@ -175,7 +175,7 @@ App::init() $endDomain->getRegisterable() !== '' ); - $isLocalHost = $request->getHostname() === 'localhost' || $request->getHostname() === 'localhost:'.$request->getPort(); + $isLocalHost = $request->getHostname() === 'localhost' || $request->getHostname() === 'localhost:' . $request->getPort(); $isIpAddress = filter_var($request->getHostname(), FILTER_VALIDATE_IP) !== false; $isConsoleProject = $project->getAttribute('$id', '') === 'console'; @@ -186,8 +186,8 @@ App::init() $isLocalHost || $isIpAddress ? null : ($isConsoleProject && $isConsoleRootSession - ? '.'.$selfDomain->getRegisterable() - : '.'.$request->getHostname() + ? '.' . $selfDomain->getRegisterable() + : '.' . $request->getHostname() ) ); @@ -231,12 +231,12 @@ App::init() throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP.'); } - return $response->redirect('https://'.$request->getHostname().$request->getURI()); + return $response->redirect('https://' . $request->getHostname() . $request->getURI()); } } if ($request->getProtocol() === 'https') { - $response->addHeader('Strict-Transport-Security', 'max-age='.(60 * 60 * 24 * 126)); // 126 days + $response->addHeader('Strict-Transport-Security', 'max-age=' . (60 * 60 * 24 * 126)); // 126 days } $response @@ -246,7 +246,8 @@ App::init() ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma') ->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $refDomain) - ->addHeader('Access-Control-Allow-Credentials', 'true'); + ->addHeader('Access-Control-Allow-Credentials', 'true') + ; /* * Validate Client Domain - Check to avoid CSRF attack @@ -257,7 +258,7 @@ App::init() $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); if ( - ! $originValidator->isValid($origin) + !$originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) @@ -297,7 +298,7 @@ App::init() $authKey = $request->getHeader('x-appwrite-key', ''); - if (! empty($authKey)) { // API Key authentication + if (!empty($authKey)) { // API Key authentication // Check if given key match project API keys $key = $project->find('secret', $authKey, 'keys'); @@ -309,7 +310,7 @@ App::init() $user = new Document([ '$id' => '', 'status' => true, - 'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(), + 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', 'name' => $project->getAttribute('name', 'Untitled'), ]); @@ -318,8 +319,8 @@ App::init() $scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', [])); $expire = $key->getAttribute('expire'); - if (! empty($expire) && $expire < DateTime::formatTz(DateTime::now())) { - throw new AppwriteException(AppwriteException::PROJECT_KEY_EXPIRED); + if (!empty($expire) && $expire < DateTime::formatTz(DateTime::now())) { + throw new AppwriteException(AppwriteException:: PROJECT_KEY_EXPIRED); } Authorization::setRole(Auth::USER_ROLE_APPS); @@ -336,7 +337,7 @@ App::init() $sdk = $request->getHeader('x-sdk-name', 'UNKNOWN'); if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); - if (! in_array($sdk, $sdks)) { + if (!in_array($sdk, $sdks)) { array_push($sdks, $sdk); $key->setAttribute('sdks', $sdks); @@ -356,22 +357,22 @@ App::init() } $service = $route->getLabel('sdk.namespace', ''); - if (! empty($service)) { + if (!empty($service)) { if ( array_key_exists($service, $project->getAttribute('services', [])) - && ! $project->getAttribute('services', [])[$service] - && ! (Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) + && !$project->getAttribute('services', [])[$service] + && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED); } } - if (! \in_array($scope, $scopes)) { + if (!\in_array($scope, $scopes)) { if ($project->isEmpty()) { // Check if permission is denied because project is missing throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } - throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User').' (role: '.\strtolower($roles[$role]['label']).') missing scope ('.$scope.')'); + throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')'); } if (false === $user->getAttribute('status')) { // Account is blocked @@ -387,6 +388,7 @@ App::options() ->inject('request') ->inject('response') ->action(function (Request $request, Response $response) { + $origin = $request->getOrigin(); $response @@ -408,6 +410,7 @@ App::error() ->inject('logger') ->inject('loggerBreadcrumbs') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, array $loggerBreadcrumbs) { + $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->match($request); @@ -422,11 +425,11 @@ App::error() $log = new Utopia\Logger\Log(); - if (isset($user) && ! $user->isEmpty()) { + if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); } - $log->setNamespace('http'); + $log->setNamespace("http"); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); @@ -439,7 +442,7 @@ App::error() $log->addTag('code', $error->getCode()); $log->addTag('projectId', $project->getId()); $log->addTag('hostname', $request->getHostname()); - $log->addTag('locale', (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); + $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); @@ -447,7 +450,7 @@ App::error() $log->addExtra('detailedTrace', $error->getTrace()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel('sdk.namespace', 'UNKNOWN_NAMESPACE').'.'.$route->getLabel('sdk.method', 'UNKNOWN_METHOD'); + $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); $log->setAction($action); $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; @@ -458,7 +461,7 @@ App::error() } $responseCode = $logger->addLog($log); - Console::info('Log pushed with status code: '.$responseCode); + Console::info('Log pushed with status code: ' . $responseCode); } } @@ -469,17 +472,17 @@ App::error() $trace = $error->getTrace(); if (php_sapi_name() === 'cli') { - Console::error('[Error] Timestamp: '.date('c', time())); + Console::error('[Error] Timestamp: ' . date('c', time())); if ($route) { - Console::error('[Error] Method: '.$route->getMethod()); - Console::error('[Error] URL: '.$route->getPath()); + Console::error('[Error] Method: ' . $route->getMethod()); + Console::error('[Error] URL: ' . $route->getPath()); } - Console::error('[Error] Type: '.get_class($error)); - Console::error('[Error] Message: '.$message); - Console::error('[Error] File: '.$file); - Console::error('[Error] Line: '.$line); + Console::error('[Error] Type: ' . get_class($error)); + Console::error('[Error] Message: ' . $message); + Console::error('[Error] File: ' . $file); + Console::error('[Error] Line: ' . $line); } /** Handle Utopia Errors */ @@ -500,7 +503,7 @@ App::error() } /** Wrap all exceptions inside Appwrite\Extend\Exception */ - if (! ($error instanceof AppwriteException)) { + if (!($error instanceof AppwriteException)) { $error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error); } @@ -545,7 +548,8 @@ App::error() ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') ->addHeader('Expires', '0') ->addHeader('Pragma', 'no-cache') - ->setStatusCode($code); + ->setStatusCode($code) + ; $template = ($route) ? $route->getLabel('error', null) : null; @@ -553,14 +557,15 @@ App::error() $layout = new View($template); $layout - ->setParam('title', $project->getAttribute('name').' - Error') + ->setParam('title', $project->getAttribute('name') . ' - Error') ->setParam('development', App::isDevelopment()) ->setParam('projectName', $project->getAttribute('name')) ->setParam('projectURL', $project->getAttribute('url')) ->setParam('message', $error->getMessage()) ->setParam('type', $type) ->setParam('code', $code) - ->setParam('trace', $trace); + ->setParam('trace', $trace) + ; $response->html($layout->render()); } @@ -577,7 +582,7 @@ App::get('/robots.txt') ->label('docs', false) ->inject('response') ->action(function (Response $response) { - $template = new View(__DIR__.'/../views/general/robots.phtml'); + $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); }); @@ -587,7 +592,7 @@ App::get('/humans.txt') ->label('docs', false) ->inject('response') ->action(function (Response $response) { - $template = new View(__DIR__.'/../views/general/humans.phtml'); + $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); }); @@ -606,43 +611,43 @@ App::get('/.well-known/acme-challenge/*') ...Text::ALPHABET_LOWER, ...Text::ALPHABET_UPPER, '-', - '_', + '_' ]); - if (! $validator->isValid($token) || \count($uriChunks) !== 4) { + if (!$validator->isValid($token) || \count($uriChunks) !== 4) { throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, 'Invalid challenge token.'); } $base = \realpath(APP_STORAGE_CERTIFICATES); - $absolute = \realpath($base.'/.well-known/acme-challenge/'.$token); + $absolute = \realpath($base . '/.well-known/acme-challenge/' . $token); - if (! $base) { + if (!$base) { throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Storage error'); } - if (! $absolute) { + if (!$absolute) { throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND, 'Unknown path'); } - if (! \substr($absolute, 0, \strlen($base)) === $base) { + if (!\substr($absolute, 0, \strlen($base)) === $base) { throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, 'Invalid path'); } - if (! \file_exists($absolute)) { + if (!\file_exists($absolute)) { throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND, 'Unknown path'); } $content = @\file_get_contents($absolute); - if (! $content) { + if (!$content) { throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Failed to get contents'); } $response->text($content); }); -include_once __DIR__.'/shared/api.php'; -include_once __DIR__.'/shared/api/auth.php'; +include_once __DIR__ . '/shared/api.php'; +include_once __DIR__ . '/shared/api/auth.php'; foreach (Config::getParam('services', []) as $service) { include_once $service['controller']; diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 779c361b61..892c41d872 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -3,18 +3,18 @@ global $utopia, $request, $response; use Appwrite\Extend\Exception; +use Utopia\Database\Document; +use Utopia\Validator\Host; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; -use Utopia\Database\Document; -use Utopia\Database\Helpers\ID; -use Utopia\Storage\Validator\File; use Utopia\Validator\ArrayList; -use Utopia\Validator\Host; use Utopia\Validator\Integer; -use Utopia\Validator\Nullable; use Utopia\Validator\Text; +use Utopia\Storage\Validator\File; use Utopia\Validator\WhiteList; +use Utopia\Database\Helpers\ID; +use Utopia\Validator\Nullable; App::get('/v1/mock/tests/foo') ->desc('Get Foo') @@ -220,9 +220,9 @@ App::get('/v1/mock/tests/general/headers') 'x-sdk-version' => $request->getHeader('x-sdk-version'), ]; $res = array_map(function ($key, $value) { - return $key.': '.$value; + return $key . ': ' . $value; }, array_keys($res), $res); - $res = implode('; ', $res); + $res = implode("; ", $res); $response->dynamic(new Document(['result' => $res]), Response::MODEL_MOCK); }); @@ -241,12 +241,14 @@ App::get('/v1/mock/tests/general/download') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { + $response ->setContentType('text/plain') ->addHeader('Content-Disposition', 'attachment; filename="test.txt"') - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->addHeader('X-Peak', \memory_get_peak_usage()) - ->send('GET:/v1/mock/tests/general/download:passed'); + ->send("GET:/v1/mock/tests/general/download:passed") + ; }); App::post('/v1/mock/tests/general/upload') @@ -269,13 +271,14 @@ App::post('/v1/mock/tests/general/upload') ->inject('request') ->inject('response') ->action(function (string $x, int $y, array $z, mixed $file, Request $request, Response $response) { + $file = $request->getFiles('file'); $contentRange = $request->getHeader('content-range'); $chunkSize = 5 * 1024 * 1024; // 5MB - if (! empty($contentRange)) { + if (!empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $size = $request->getContentRangeSize(); @@ -290,7 +293,7 @@ App::post('/v1/mock/tests/general/upload') throw new Exception(Exception::GENERAL_MOCK, 'Invalid content-range header'); } - if ($start === 0 && ! empty($id)) { + if ($start === 0 && !empty($id)) { throw new Exception(Exception::GENERAL_MOCK, 'First chunked request cannot have id header'); } @@ -314,7 +317,7 @@ App::post('/v1/mock/tests/general/upload') $response->json([ '$id' => ID::custom('newfileid'), 'chunksTotal' => (int) ceil($size / ($end + 1 - $start)), - 'chunksUploaded' => ceil($start / $chunkSize) + 1, + 'chunksUploaded' => ceil($start / $chunkSize) + 1 ]); } } else { @@ -327,7 +330,7 @@ App::post('/v1/mock/tests/general/upload') } if ($file['size'] !== 38756) { - throw new Exception(Exception::GENERAL_MOCK, 'Wrong file size'); + throw new Exception(Exception::GENERAL_MOCK, 'Wrong file size'); } if (\md5(\file_get_contents($file['tmp_name'])) !== 'd80e7e6999a3eb2ae0d631a96fe135a4') { @@ -350,6 +353,7 @@ App::get('/v1/mock/tests/general/redirect') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { + $response->redirect('/v1/mock/tests/general/redirect/done'); }); @@ -383,6 +387,7 @@ App::get('/v1/mock/tests/general/set-cookie') ->inject('response') ->inject('request') ->action(function (Response $response, Request $request) { + $response->addCookie('cookieName', 'cookieValue', \time() + 31536000, '/', $request->getHostname(), true, true); }); @@ -400,6 +405,7 @@ App::get('/v1/mock/tests/general/get-cookie') ->label('sdk.mock', true) ->inject('request') ->action(function (Request $request) { + if ($request->getCookie('cookieName', '') !== 'cookieValue') { throw new Exception(Exception::GENERAL_MOCK, 'Missing cookie value'); } @@ -418,6 +424,7 @@ App::get('/v1/mock/tests/general/empty') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { + $response->noContent(); }); @@ -458,9 +465,9 @@ App::get('/v1/mock/tests/general/headers') 'x-sdk-version' => $request->getHeader('x-sdk-version'), ]; $res = array_map(function ($key, $value) { - return $key.': '.$value; + return $key . ': ' . $value; }, array_keys($res), $res); - $res = implode('; ', $res); + $res = implode("; ", $res); $response->dynamic(new Document(['result' => $res]), Response::MODEL_MOCK); }); @@ -511,9 +518,11 @@ App::get('/v1/mock/tests/general/502-error') ->label('sdk.mock', true) ->inject('response') ->action(function (Response $response) { + $response ->setStatusCode(502) - ->text('This is a text error'); + ->text('This is a text error') + ; }); App::get('/v1/mock/tests/general/oauth2') @@ -528,7 +537,8 @@ App::get('/v1/mock/tests/general/oauth2') ->param('state', '', new Text(1024), 'OAuth2 state.') ->inject('response') ->action(function (string $client_id, string $redirectURI, string $scope, string $state, Response $response) { - $response->redirect($redirectURI.'?'.\http_build_query(['code' => 'abcdef', 'state' => $state])); + + $response->redirect($redirectURI . '?' . \http_build_query(['code' => 'abcdef', 'state' => $state])); }); App::get('/v1/mock/tests/general/oauth2/token') @@ -545,6 +555,7 @@ App::get('/v1/mock/tests/general/oauth2/token') ->param('refresh_token', '', new Text(100), 'OAuth2 refresh token.', true) ->inject('response') ->action(function (string $client_id, string $client_secret, string $grantType, string $redirectURI, string $code, string $refreshToken, Response $response) { + if ($client_id != '1') { throw new Exception(Exception::GENERAL_MOCK, 'Invalid client ID'); } @@ -556,7 +567,7 @@ App::get('/v1/mock/tests/general/oauth2/token') $responseJson = [ 'access_token' => '123456', 'refresh_token' => 'tuvwxyz', - 'expires_in' => 14400, + 'expires_in' => 14400 ]; if ($grantType === 'authorization_code') { @@ -584,6 +595,7 @@ App::get('/v1/mock/tests/general/oauth2/user') ->param('token', '', new Text(100), 'OAuth2 Access Token.') ->inject('response') ->action(function (string $token, Response $response) { + if ($token != '123456') { throw new Exception(Exception::GENERAL_MOCK, 'Invalid token'); } @@ -602,6 +614,7 @@ App::get('/v1/mock/tests/general/oauth2/success') ->label('docs', false) ->inject('response') ->action(function (Response $response) { + $response->json([ 'result' => 'success', ]); @@ -614,6 +627,7 @@ App::get('/v1/mock/tests/general/oauth2/failure') ->label('docs', false) ->inject('response') ->action(function (Response $response) { + $response ->setStatusCode(Response::STATUS_CODE_BAD_REQUEST) ->json([ @@ -627,22 +641,23 @@ App::shutdown() ->inject('response') ->inject('request') ->action(function (App $utopia, Response $response, Request $request) { - $result = []; - $route = $utopia->match($request); - $path = APP_STORAGE_CACHE.'/tests.json'; - $tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : []; - if (! \is_array($tests)) { + $result = []; + $route = $utopia->match($request); + $path = APP_STORAGE_CACHE . '/tests.json'; + $tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : []; + + if (!\is_array($tests)) { throw new Exception(Exception::GENERAL_MOCK, 'Failed to read results', 500); } - $result[$route->getMethod().':'.$route->getPath()] = true; + $result[$route->getMethod() . ':' . $route->getPath()] = true; $tests = \array_merge($tests, $result); - if (! \file_put_contents($path, \json_encode($tests), LOCK_EX)) { + if (!\file_put_contents($path, \json_encode($tests), LOCK_EX)) { throw new Exception(Exception::GENERAL_MOCK, 'Failed to save results', 500); } - $response->dynamic(new Document(['result' => $route->getMethod().':'.$route->getPath().':passed']), Response::MODEL_MOCK); + $response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getPath() . ':passed']), Response::MODEL_MOCK); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index ad7b3d135d..2bbac41811 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -7,14 +7,14 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\Mail; -use Appwrite\Event\Usage; use Appwrite\Extend\Exception; +use Appwrite\Event\Usage; use Appwrite\Messaging\Adapter\Realtime; -use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Request; +use Utopia\App; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; -use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; use Utopia\Database\Database; @@ -36,7 +36,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar $replace = $parts[1] ?? ''; $params = match ($namespace) { - 'user' => (array) $user, + 'user' => (array)$user, 'request' => $requestParams, default => $responsePayload, }; @@ -45,11 +45,11 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar $label = \str_replace($find, $params[$replace], $label); } } - return $label; }; $databaseListener = function (string $event, Document $document, Document $project, Usage $queueForUsage, Database $dbForProject) { + $value = 1; if ($event === Database::EVENT_DOCUMENT_DELETE) { $value = -1; @@ -81,13 +81,13 @@ $databaseListener = function (string $event, Document $document, Document $proje ->addReduce($document); } break; - case str_starts_with($document->getCollection(), 'database_') && ! str_contains($document->getCollection(), 'collection'): //collections + case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; $queueForUsage ->addMetric(METRIC_COLLECTIONS, $value) // per project ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value) // per database -; + ; if ($event === Database::EVENT_DOCUMENT_DELETE) { $queueForUsage @@ -96,7 +96,7 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_'): //documents $parts = explode('_', $document->getCollection()); - $databaseInternalId = $parts[1] ?? 0; + $databaseInternalId = $parts[1] ?? 0; $collectionInternalId = $parts[3] ?? 0; $queueForUsage ->addMetric(METRIC_DOCUMENTS, $value) // per project @@ -132,13 +132,13 @@ $databaseListener = function (string $event, Document $document, Document $proje ->addMetric(METRIC_DEPLOYMENTS, $value) // per project ->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value)// per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value); // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);// per function break; case $document->getCollection() === 'executions': $queueForUsage ->addMetric(METRIC_EXECUTIONS, $value) // per project - ->addMetric(str_replace('{functionInternalId}', $document->getAttribute('functionInternalId'), METRIC_FUNCTION_ID_EXECUTIONS), $value); // per function + ->addMetric(str_replace('{functionInternalId}', $document->getAttribute('functionInternalId'), METRIC_FUNCTION_ID_EXECUTIONS), $value);// per function break; default: break; @@ -161,6 +161,7 @@ App::init() ->inject('mode') ->inject('mails') ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Delete $deletes, EventDatabase $database, Database $dbForProject, Usage $queueForUsage, string $mode, Mail $mails) use ($databaseListener) { + $route = $utopia->match($request); if ($project->isEmpty() && $route->getLabel('abuse-limit', 0) > 0) { // Abuse limit requires an active project scope @@ -173,7 +174,7 @@ App::init() $abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}'); $timeLimitArray = []; - $abuseKeyLabel = (! is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel; + $abuseKeyLabel = (!is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel; foreach ($abuseKeyLabel as $abuseKey) { $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject); @@ -181,7 +182,7 @@ App::init() ->setParam('{userId}', $user->getId()) ->setParam('{userAgent}', $request->getUserAgent('')) ->setParam('{ip}', $request->getIP()) - ->setParam('{url}', $request->getHostname().$route->getPath()) + ->setParam('{url}', $request->getHostname() . $route->getPath()) ->setParam('{method}', $request->getMethod()); $timeLimitArray[] = $timeLimit; } @@ -194,8 +195,8 @@ App::init() foreach ($timeLimitArray as $timeLimit) { foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys - if (! empty($value)) { - $timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value); + if (!empty($value)) { + $timeLimit->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value); } } @@ -209,15 +210,16 @@ App::init() $response ->addHeader('X-RateLimit-Limit', $limit) ->addHeader('X-RateLimit-Remaining', $remaining) - ->addHeader('X-RateLimit-Reset', $time); + ->addHeader('X-RateLimit-Reset', $time) + ; } $enabled = App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; if ( $enabled // Abuse is enabled - && ! $isAppUser // User is not API key - && ! $isPrivilegedUser // User is not an admin + && !$isAppUser // User is not API key + && !$isPrivilegedUser // User is not an admin && $abuse->check() // Route is rate-limited ) { throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); @@ -241,7 +243,7 @@ App::init() ->setUser($user); $smtp = $project->getAttribute('smtp', []); - if (! empty($smtp) && ($smtp['enabled'] ?? false)) { + if (!empty($smtp) && ($smtp['enabled'] ?? false)) { $mails ->setSmtpHost($smtp['host'] ?? '') ->setSmtpPort($smtp['port'] ?? 25) @@ -263,14 +265,14 @@ App::init() $useCache = $route->getLabel('cache', false); if ($useCache) { - $key = md5($request->getURI().implode('*', $request->getParams())).'*'.APP_CACHE_BUSTER; + $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$project->getId()) + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); $timestamp = 60 * 60 * 24 * 30; $data = $cache->load($key, $timestamp); - if (! empty($data)) { + if (!empty($data)) { $data = json_decode($data, true); $parts = explode('/', $data['resourceType']); $type = $parts[0] ?? null; @@ -280,24 +282,24 @@ App::init() $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (! $fileSecurity && ! $valid) { + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } $parts = explode('/', $data['resource']); $fileId = $parts[1] ?? null; - if ($fileSecurity && ! $valid) { - $file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId); + if ($fileSecurity && !$valid) { + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -306,10 +308,11 @@ App::init() } $response - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp).' GMT') + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT') ->addHeader('X-Appwrite-Cache', 'hit') ->setContentType($data['contentType']) - ->send(base64_decode($data['payload'])); + ->send(base64_decode($data['payload'])) + ; $route->setIsActive(false); } else { @@ -324,6 +327,7 @@ App::init() ->inject('request') ->inject('project') ->action(function (App $utopia, Request $request, Document $project) { + $route = $utopia->match($request); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -427,9 +431,10 @@ App::shutdown() ->inject('mode') ->inject('dbForConsole') ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Delete $deletes, EventDatabase $database, Database $dbForProject, Func $queueForFunctions, Usage $queueForUsage, string $mode, Database $dbForConsole) use ($parseLabel) { + $responsePayload = $response->getPayload(); - if (! empty($events->getEvent())) { + if (!empty($events->getEvent())) { if (empty($events->getPayload())) { $events->setPayload($responsePayload); } @@ -478,7 +483,7 @@ App::shutdown() roles: $target['roles'], options: [ 'permissionsChanged' => $target['permissionsChanged'], - 'userId' => $events->getParam('userId'), + 'userId' => $events->getParam('userId') ] ); } @@ -491,24 +496,24 @@ App::shutdown() * Audit labels */ $pattern = $route->getLabel('audits.resource', null); - if (! empty($pattern)) { + if (!empty($pattern)) { $resource = $parseLabel($pattern, $responsePayload, $requestParams, $user); - if (! empty($resource) && $resource !== $pattern) { + if (!empty($resource) && $resource !== $pattern) { $audits->setResource($resource); } } - if (! $user->isEmpty()) { + if (!$user->isEmpty()) { $audits->setUser($user); } - if (! empty($audits->getResource()) && ! empty($audits->getUser()->getId())) { + if (!empty($audits->getResource()) && !empty($audits->getUser()->getId())) { /** * audits.payload is switched to default true * in order to auto audit payload for all endpoints */ $pattern = $route->getLabel('audits.payload', true); - if (! empty($pattern)) { + if (!empty($pattern)) { $audits->setPayload($responsePayload); } @@ -518,11 +523,11 @@ App::shutdown() $audits->trigger(); } - if (! empty($deletes->getType())) { + if (!empty($deletes->getType())) { $deletes->trigger(); } - if (! empty($database->getType())) { + if (!empty($database->getType())) { $database->trigger(); } @@ -534,35 +539,35 @@ App::shutdown() $resource = $resourceType = null; $data = $response->getPayload(); - if (! empty($data['payload'])) { + if (!empty($data['payload'])) { $pattern = $route->getLabel('cache.resource', null); - if (! empty($pattern)) { + if (!empty($pattern)) { $resource = $parseLabel($pattern, $responsePayload, $requestParams, $user); } $pattern = $route->getLabel('cache.resourceType', null); - if (! empty($pattern)) { + if (!empty($pattern)) { $resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user); } - $key = md5($request->getURI().implode('*', $request->getParams())).'*'.APP_CACHE_BUSTER; + $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; $data = json_encode([ 'resourceType' => $resourceType, 'resource' => $resource, 'contentType' => $response->getContentType(), 'payload' => base64_encode($data['payload']), - ]); + ]) ; $signature = md5($data); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); $now = DateTime::now(); if ($cacheLog->isEmpty()) { Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ - '$id' => $key, - 'resource' => $resource, - 'accessedAt' => $now, - 'signature' => $signature, + '$id' => $key, + 'resource' => $resource, + 'accessedAt' => $now, + 'signature' => $signature, ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); @@ -571,18 +576,20 @@ App::shutdown() if ($signature !== $cacheLog->getAttribute('signature')) { $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$project->getId()) + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); $cache->save($key, $data); } } } + + if ($project->getId() !== 'console') { if ($mode !== APP_MODE_ADMIN) { $fileSize = 0; $file = $request->getFiles('file'); - if (! empty($file)) { + if (!empty($file)) { $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } @@ -600,7 +607,7 @@ App::shutdown() /** * Update user last activity */ - if (! $user->isEmpty()) { + if (!$user->isEmpty()) { $accessedAt = $user->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCCESS)) > $accessedAt) { $user->setAttribute('accessedAt', DateTime::now()); diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index acb8410804..5b1af0d36c 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -1,9 +1,9 @@ inject('request') ->inject('project') ->action(function (App $utopia, Request $request, Document $project) { + $route = $utopia->match($request); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index 37914dda37..dcf9c80a51 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -11,9 +11,9 @@ App::init() ->action(function (Request $request, Response $response) { $response ->addHeader('X-Frame-Options', 'SAMEORIGIN') // Avoid console and homepage from showing in iframes - ->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url='.\urlencode($request->getURI())) + ->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url=' . \urlencode($request->getURI())) ->addHeader('X-UA-Compatible', 'IE=Edge') // Deny IE browsers from going into quirks mode -; + ; }); App::get('/console/*') @@ -30,41 +30,41 @@ App::get('/console/*') ->inject('request') ->inject('response') ->action(function (Request $request, Response $response) { - $fallback = file_get_contents(__DIR__.'/../../../console/index.html'); + $fallback = file_get_contents(__DIR__ . '/../../../console/index.html'); // Card SSR if (\str_starts_with($request->getURI(), '/card')) { $urlCunks = \explode('/', $request->getURI()); $userId = $urlCunks[\count($urlCunks) - 1] ?? ''; - $domain = $request->getProtocol().'://'.$request->getHostname(); + $domain = $request->getProtocol() . '://' . $request->getHostname(); - if (! empty($userId)) { - $ogImageUrl = $domain.'/v1/cards/cloud-og?userId='.$userId; + if (!empty($userId)) { + $ogImageUrl = $domain . '/v1/cards/cloud-og?userId=' . $userId; } else { - $ogImageUrl = $domain.'/v1/cards/cloud-og?mock=normal'; + $ogImageUrl = $domain . '/v1/cards/cloud-og?mock=normal'; } $ogTags = [ 'Appwrite Cloud Card', '', - '', + '', '', '', '', '', '', '', - '', + '', '', - '', - '', + '', + '', '', '', '', '', '', - '', + '', ]; $fallback = \str_replace('', \implode('', $ogTags), $fallback); diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index fb33350792..e90f3ec25b 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -24,14 +24,14 @@ App::get('/versions') continue; } - if (isset($language['enabled']) && ! $language['enabled']) { + if (isset($language['enabled']) && !$language['enabled']) { continue; } $platformKey = $platform['key'] ?? ''; $languageKey = $language['key'] ?? ''; $version = $language['version'] ?? ''; - $versions[$platformKey.'-'.$languageKey] = $version; + $versions[$platformKey . '-' . $languageKey] = $version; } } diff --git a/app/http.php b/app/http.php index 88ee35ff1f..8ce7b6f017 100644 --- a/app/http.php +++ b/app/http.php @@ -1,30 +1,30 @@ on('WorkerStart', function ($server, $workerId) { - Console::success('Worker '.++$workerId.' started successfully'); + Console::success('Worker ' . ++$workerId . ' started successfully'); }); $http->on('BeforeReload', function ($server, $workerId) { @@ -53,16 +53,16 @@ $http->on('AfterReload', function ($server, $workerId) { Console::success('Reload completed...'); }); -Files::load(__DIR__.'/../console'); +Files::load(__DIR__ . '/../console'); -include __DIR__.'/controllers/general.php'; +include __DIR__ . '/controllers/general.php'; $http->on('start', function (Server $http) use ($payloadSize, $register) { $app = new App('UTC'); go(function () use ($register, $app) { $pools = $register->get('pools'); /** @var Group $pools */ - App::setResource('pools', fn () => $pools); + App::setResource('pools', fn() => $pools); // wait for database to be ready $attempts = 0; @@ -77,7 +77,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { } catch (\Exception $e) { Console::warning("Database not ready. Retrying connection ({$attempts})..."); if ($attempts >= $max) { - throw new \Exception('Failed to connect to database: '.$e->getMessage()); + throw new \Exception('Failed to connect to database: ' . $e->getMessage()); } sleep($sleep); } @@ -98,7 +98,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { } if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) { - $adapter = new TimeLimit('', 0, 1, $dbForConsole); + $adapter = new TimeLimit("", 0, 1, $dbForConsole); $adapter->setup(); } @@ -109,11 +109,11 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { if (($collection['$collection'] ?? '') !== Database::METADATA) { continue; } - if (! $dbForConsole->getCollection($key)->isEmpty()) { + if (!$dbForConsole->getCollection($key)->isEmpty()) { continue; } - Console::success('[Setup] - Creating collection: '.$collection['$id'].'...'); + Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...'); $attributes = []; $indexes = []; @@ -128,7 +128,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '', + 'format' => $attribute['format'] ?? '' ]); } @@ -145,7 +145,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { $dbForConsole->createCollection($key, $attributes, $indexes); } - if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && ! $dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) { + if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) { Console::success('[Setup] - Creating default bucket...'); $dbForConsole->createDocument('buckets', new Document([ '$id' => ID::custom('default'), @@ -188,7 +188,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { 'array' => $attribute['array'], 'filters' => $attribute['filters'], 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '', + 'format' => $attribute['format'] ?? '' ]); } @@ -202,7 +202,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { ]); } - $dbForConsole->createCollection('bucket_'.$bucket->getInternalId(), $attributes, $indexes); + $dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); } $pools->reclaim(); @@ -210,7 +210,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { Console::success('[Setup] - Server database init completed...'); }); - Console::success('Server started successfully (max payload is '.number_format($payloadSize).' bytes)'); + Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)'); Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}"); // listen ctrl + c @@ -229,8 +229,8 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $response ->setContentType(Files::getFileMimeType($request->getURI())) - ->addHeader('Cache-Control', 'public, max-age='.$time) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache + ->addHeader('Cache-Control', 'public, max-age=' . $time) + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache ->send(Files::getFileContents($request->getURI())); return; @@ -239,7 +239,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $app = new App('UTC'); $pools = $register->get('pools'); - App::setResource('pools', fn () => $pools); + App::setResource('pools', fn() => $pools); try { Authorization::cleanRoles(); @@ -249,7 +249,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } catch (\Throwable $th) { $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); - $logger = $app->getResource('logger'); + $logger = $app->getResource("logger"); if ($logger) { try { /** @var Utopia\Database\Document $user */ @@ -258,16 +258,16 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo // All good, user is optional information for logger } - $loggerBreadcrumbs = $app->getResource('loggerBreadcrumbs'); + $loggerBreadcrumbs = $app->getResource("loggerBreadcrumbs"); $route = $app->match($request); $log = new Utopia\Logger\Log(); - if (isset($user) && ! $user->isEmpty()) { + if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); } - $log->setNamespace('http'); + $log->setNamespace("http"); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); @@ -279,7 +279,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log->addTag('code', $th->getCode()); // $log->addTag('projectId', $project->getId()); // TODO: Figure out how to get ProjectID, if it becomes relevant $log->addTag('hostname', $request->getHostname()); - $log->addTag('locale', (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); + $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); @@ -287,7 +287,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log->addExtra('detailedTrace', $th->getTrace()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel('sdk.namespace', 'UNKNOWN_NAMESPACE').'.'.$route->getLabel('sdk.method', 'UNKNOWN_METHOD'); + $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); $log->setAction($action); $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; @@ -298,18 +298,18 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } $responseCode = $logger->addLog($log); - Console::info('Log pushed with status code: '.$responseCode); + Console::info('Log pushed with status code: ' . $responseCode); } - Console::error('[Error] Type: '.get_class($th)); - Console::error('[Error] Message: '.$th->getMessage()); - Console::error('[Error] File: '.$th->getFile()); - Console::error('[Error] Line: '.$th->getLine()); + Console::error('[Error] Type: ' . get_class($th)); + Console::error('[Error] Message: ' . $th->getMessage()); + Console::error('[Error] File: ' . $th->getFile()); + Console::error('[Error] Line: ' . $th->getLine()); $swooleResponse->setStatusCode(500); $output = ((App::isDevelopment())) ? [ - 'message' => 'Error: '.$th->getMessage(), + 'message' => 'Error: ' . $th->getMessage(), 'code' => 500, 'file' => $th->getFile(), 'line' => $th->getLine(), diff --git a/app/init.php b/app/init.php index 2eb066e737..ea3a039ec9 100644 --- a/app/init.php +++ b/app/init.php @@ -5,9 +5,11 @@ * * Initializes both Appwrite API entry point, queue workers, and CLI tasks. * Set configuration, framework resources & app constants + * */ -if (\file_exists(__DIR__.'/../vendor/autoload.php')) { - require_once __DIR__.'/../vendor/autoload.php'; + +if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { + require_once __DIR__ . '/../vendor/autoload.php'; } ini_set('memory_limit', '512M'); @@ -16,54 +18,41 @@ ini_set('display_startup_errors', 1); ini_set('default_socket_timeout', -1); error_reporting(E_ALL); -use Ahc\Jwt\JWT; -use Ahc\Jwt\JWTException; +use Appwrite\Event\Usage; +use Appwrite\Extend\Exception; use Appwrite\Auth\Auth; use Appwrite\Event\Audit; use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Delete; use Appwrite\Event\Event; -use Appwrite\Event\Func; use Appwrite\Event\Mail; use Appwrite\Event\Phone; -use Appwrite\Event\Usage; -use Appwrite\Extend\Exception; -use Appwrite\GraphQL\Promises\Adapter\Swoole; +use Appwrite\Event\Delete; use Appwrite\GraphQL\Schema; use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Origin; use Appwrite\OpenSSL\OpenSSL; use Appwrite\URL\URL as AppwriteURL; -use MaxMind\Db\Reader; -use PHPMailer\PHPMailer\PHPMailer; -use Swoole\Database\PDOProxy; use Utopia\App; +use Utopia\Logger\Logger; use Utopia\Cache\Adapter\Redis as RedisCache; -use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\Config\Config; -use Utopia\Database\Adapter\MariaDB; -use Utopia\Database\Adapter\MySQL; +use Utopia\Database\Helpers\ID; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Structure; -use Utopia\DSN\DSN; use Utopia\Locale\Locale; -use Utopia\Logger\Logger; +use Utopia\DSN\DSN; use Utopia\Messaging\Adapters\SMS\Mock; +use Appwrite\GraphQL\Promises\Adapter\Swoole; use Utopia\Messaging\Adapters\SMS\Msg91; use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; use Utopia\Messaging\Adapters\SMS\Twilio; use Utopia\Messaging\Adapters\SMS\Vonage; -use Utopia\Pools\Group; -use Utopia\Pools\Pool; -use Utopia\Queue; -use Utopia\Queue\Connection; use Utopia\Registry\Registry; use Utopia\Storage\Device; use Utopia\Storage\Device\Backblaze; @@ -72,9 +61,22 @@ use Utopia\Storage\Device\Linode; use Utopia\Storage\Device\Local; use Utopia\Storage\Device\S3; use Utopia\Storage\Device\Wasabi; +use Utopia\Cache\Adapter\Sharding; +use Utopia\Database\Adapter\MariaDB; +use Utopia\Database\Adapter\MySQL; +use Utopia\Pools\Group; +use Utopia\Pools\Pool; +use Ahc\Jwt\JWT; +use Ahc\Jwt\JWTException; +use Appwrite\Event\Func; +use MaxMind\Db\Reader; +use PHPMailer\PHPMailer\PHPMailer; +use Swoole\Database\PDOProxy; +use Utopia\Queue; +use Utopia\Queue\Connection; use Utopia\Storage\Storage; -use Utopia\Validator\IP; use Utopia\Validator\Range; +use Utopia\Validator\IP; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; @@ -82,7 +84,7 @@ const APP_NAME = 'Appwrite'; const APP_DOMAIN = 'appwrite.io'; const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address const APP_EMAIL_SECURITY = ''; // Default security email address -const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s'; +const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s'; const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; @@ -160,7 +162,7 @@ const DELETE_TYPE_REALTIME = 'realtime'; const DELETE_TYPE_BUCKETS = 'buckets'; const DELETE_TYPE_SESSIONS = 'sessions'; const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp'; -const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; +const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; const DELETE_TYPE_SCHEDULES = 'schedules'; // Compression type const COMPRESSION_TYPE_NONE = 'none'; @@ -182,7 +184,7 @@ const MAX_OUTPUT_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; -const METRIC_SESSIONS = 'sessions'; +const METRIC_SESSIONS = 'sessions'; const METRIC_DATABASES = 'databases'; const METRIC_COLLECTIONS = 'collections'; const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections'; @@ -190,28 +192,28 @@ const METRIC_DOCUMENTS = 'documents'; const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; const METRIC_BUCKETS = 'buckets'; -const METRIC_FILES = 'files'; -const METRIC_FILES_STORAGE = 'files.storage'; +const METRIC_FILES = 'files'; +const METRIC_FILES_STORAGE = 'files.storage'; const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files'; -const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; -const METRIC_FUNCTIONS = 'functions'; -const METRIC_DEPLOYMENTS = 'deployments'; -const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; -const METRIC_BUILDS = 'builds'; -const METRIC_BUILDS_STORAGE = 'builds.storage'; -const METRIC_BUILDS_COMPUTE = 'builds.compute'; -const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; +const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; +const METRIC_FUNCTIONS = 'functions'; +const METRIC_DEPLOYMENTS = 'deployments'; +const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; +const METRIC_BUILDS = 'builds'; +const METRIC_BUILDS_STORAGE = 'builds.storage'; +const METRIC_BUILDS_COMPUTE = 'builds.compute'; +const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; -const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; -const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; -const METRIC_EXECUTIONS = 'executions'; -const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; -const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; -const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; -const METRIC_NETWORK_REQUESTS = 'network.requests'; -const METRIC_NETWORK_INBOUND = 'network.inbound'; -const METRIC_NETWORK_OUTBOUND = 'network.outbound'; +const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; +const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; +const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; +const METRIC_EXECUTIONS = 'executions'; +const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; +const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; +const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; +const METRIC_NETWORK_REQUESTS = 'network.requests'; +const METRIC_NETWORK_INBOUND = 'network.inbound'; +const METRIC_NETWORK_OUTBOUND = 'network.outbound'; $register = new Registry(); @@ -220,42 +222,42 @@ App::setMode(App::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION)); /* * ENV vars */ -Config::load('events', __DIR__.'/config/events.php'); -Config::load('auth', __DIR__.'/config/auth.php'); -Config::load('errors', __DIR__.'/config/errors.php'); -Config::load('authProviders', __DIR__.'/config/authProviders.php'); -Config::load('platforms', __DIR__.'/config/platforms.php'); -Config::load('collections', __DIR__.'/config/collections.php'); -Config::load('runtimes', __DIR__.'/config/runtimes.php'); -Config::load('usage', __DIR__.'/config/usage.php'); -Config::load('roles', __DIR__.'/config/roles.php'); // User roles and scopes -Config::load('scopes', __DIR__.'/config/scopes.php'); // User roles and scopes -Config::load('services', __DIR__.'/config/services.php'); // List of services -Config::load('variables', __DIR__.'/config/variables.php'); // List of env variables -Config::load('regions', __DIR__.'/config/regions.php'); // List of available regions -Config::load('avatar-browsers', __DIR__.'/config/avatars/browsers.php'); -Config::load('avatar-credit-cards', __DIR__.'/config/avatars/credit-cards.php'); -Config::load('avatar-flags', __DIR__.'/config/avatars/flags.php'); -Config::load('locale-codes', __DIR__.'/config/locale/codes.php'); -Config::load('locale-currencies', __DIR__.'/config/locale/currencies.php'); -Config::load('locale-eu', __DIR__.'/config/locale/eu.php'); -Config::load('locale-languages', __DIR__.'/config/locale/languages.php'); -Config::load('locale-phones', __DIR__.'/config/locale/phones.php'); -Config::load('locale-countries', __DIR__.'/config/locale/countries.php'); -Config::load('locale-continents', __DIR__.'/config/locale/continents.php'); -Config::load('locale-templates', __DIR__.'/config/locale/templates.php'); -Config::load('storage-logos', __DIR__.'/config/storage/logos.php'); -Config::load('storage-mimes', __DIR__.'/config/storage/mimes.php'); -Config::load('storage-inputs', __DIR__.'/config/storage/inputs.php'); -Config::load('storage-outputs', __DIR__.'/config/storage/outputs.php'); -Config::load('messagingProviders', __DIR__.'/config/messagingProviders.php'); +Config::load('events', __DIR__ . '/config/events.php'); +Config::load('auth', __DIR__ . '/config/auth.php'); +Config::load('errors', __DIR__ . '/config/errors.php'); +Config::load('authProviders', __DIR__ . '/config/authProviders.php'); +Config::load('platforms', __DIR__ . '/config/platforms.php'); +Config::load('collections', __DIR__ . '/config/collections.php'); +Config::load('runtimes', __DIR__ . '/config/runtimes.php'); +Config::load('usage', __DIR__ . '/config/usage.php'); +Config::load('roles', __DIR__ . '/config/roles.php'); // User roles and scopes +Config::load('scopes', __DIR__ . '/config/scopes.php'); // User roles and scopes +Config::load('services', __DIR__ . '/config/services.php'); // List of services +Config::load('variables', __DIR__ . '/config/variables.php'); // List of env variables +Config::load('regions', __DIR__ . '/config/regions.php'); // List of available regions +Config::load('avatar-browsers', __DIR__ . '/config/avatars/browsers.php'); +Config::load('avatar-credit-cards', __DIR__ . '/config/avatars/credit-cards.php'); +Config::load('avatar-flags', __DIR__ . '/config/avatars/flags.php'); +Config::load('locale-codes', __DIR__ . '/config/locale/codes.php'); +Config::load('locale-currencies', __DIR__ . '/config/locale/currencies.php'); +Config::load('locale-eu', __DIR__ . '/config/locale/eu.php'); +Config::load('locale-languages', __DIR__ . '/config/locale/languages.php'); +Config::load('locale-phones', __DIR__ . '/config/locale/phones.php'); +Config::load('locale-countries', __DIR__ . '/config/locale/countries.php'); +Config::load('locale-continents', __DIR__ . '/config/locale/continents.php'); +Config::load('locale-templates', __DIR__ . '/config/locale/templates.php'); +Config::load('storage-logos', __DIR__ . '/config/storage/logos.php'); +Config::load('storage-mimes', __DIR__ . '/config/storage/mimes.php'); +Config::load('storage-inputs', __DIR__ . '/config/storage/inputs.php'); +Config::load('storage-outputs', __DIR__ . '/config/storage/outputs.php'); +Config::load('messagingProviders', __DIR__ . '/config/messagingProviders.php'); $user = App::getEnv('_APP_REDIS_USER', ''); $pass = App::getEnv('_APP_REDIS_PASS', ''); -if (! empty($user) || ! empty($pass)) { - Resque::setBackend('redis://'.$user.':'.$pass.'@'.App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', '')); +if (!empty($user) || !empty($pass)) { + Resque::setBackend('redis://' . $user . ':' . $pass . '@' . App::getEnv('_APP_REDIS_HOST', '') . ':' . App::getEnv('_APP_REDIS_PORT', '')); } else { - Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', '')); + Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '') . ':' . App::getEnv('_APP_REDIS_PORT', '')); } /** @@ -311,7 +313,8 @@ Database::addFilter( if (isset($formatOptions['min']) || isset($formatOptions['max'])) { $attribute ->setAttribute('min', $formatOptions['min']) - ->setAttribute('max', $formatOptions['max']); + ->setAttribute('max', $formatOptions['max']) + ; } return $value; @@ -434,7 +437,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return Authorization::skip(fn() => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -448,7 +451,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return Authorization::skip(fn() => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -490,7 +493,7 @@ Database::addFilter( return null; } $value = json_decode($value, true); - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$value['version']); + $key = App::getEnv('_APP_OPENSSL_KEY_V' . $value['version']); return OpenSSL::decrypt($value['data'], $value['method'], $key, 0, hex2bin($value['iv']), hex2bin($value['tag'])); } @@ -503,11 +506,11 @@ Database::addFilter( $user->getId(), $user->getAttribute('email', ''), $user->getAttribute('name', ''), - $user->getAttribute('phone', ''), + $user->getAttribute('phone', '') ]; foreach ($user->getAttribute('labels', []) as $label) { - $searchValues[] = 'label:'.$label; + $searchValues[] = 'label:' . $label; } $search = implode(' ', \array_filter($searchValues)); @@ -525,7 +528,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return Authorization::skip(fn() => $database ->find('targets', [ Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -539,7 +542,7 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - $provider = Authorization::skip(fn () => $database + $provider = Authorization::skip(fn() => $database ->findOne('providers', [ Query::equal('$id', [$document->getAttribute('providerId')]), Query::select(['type']), @@ -548,7 +551,6 @@ Database::addFilter( if ($provider) { return $provider->getAttribute('type'); } - return null; } ); @@ -566,7 +568,6 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () { Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) { $elements = $attribute['formatOptions']['elements']; - return new WhiteList($elements, true); }, Database::VAR_STRING); @@ -581,14 +582,12 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () { Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) { $min = $attribute['formatOptions']['min'] ?? -INF; $max = $attribute['formatOptions']['max'] ?? INF; - return new Range($min, $max, Range::TYPE_INTEGER); }, Database::VAR_INTEGER); Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) { $min = $attribute['formatOptions']['min'] ?? -INF; $max = $attribute['formatOptions']['max'] ?? INF; - return new Range($min, $max, Range::TYPE_FLOAT); }, Database::VAR_FLOAT); @@ -604,13 +603,12 @@ $register->set('logger', function () { return null; } - if (! Logger::hasProvider($providerName)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Logging provider not supported. Logging is disabled'); + if (!Logger::hasProvider($providerName)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); } - $classname = '\\Utopia\\Logger\\Adapter\\'.\ucfirst($providerName); + $classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName); $adapter = new $classname($providerConfig); - return new Logger($adapter); }); $register->set('pools', function () { @@ -679,7 +677,7 @@ $register->set('pools', function () { throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500); } - $poolSize = (int) ($instanceConnections / $workerCount); + $poolSize = (int)($instanceConnections / $workerCount); foreach ($connections as $key => $connection) { $type = $connection['type'] ?? ''; @@ -690,7 +688,7 @@ $register->set('pools', function () { $dsns = explode(',', $connection['dsns'] ?? ''); foreach ($dsns as &$dsn) { $dsn = explode('=', $dsn); - $name = ($multipe) ? $key.'_'.$dsn[0] : $key; + $name = ($multipe) ? $key . '_' . $dsn[0] : $key; $dsn = $dsn[1] ?? ''; $config[] = $name; if (empty($dsn)) { @@ -706,8 +704,8 @@ $register->set('pools', function () { $dsnScheme = $dsn->getScheme(); $dsnDatabase = $dsn->getPath(); - if (! in_array($dsnScheme, $schemes)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid console database scheme'); + if (!in_array($dsnScheme, $schemes)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); } /** @@ -722,21 +720,21 @@ $register->set('pools', function () { case 'mariadb': $resource = function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [ + return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array( PDO::ATTR_TIMEOUT => 3, // Seconds PDO::ATTR_PERSISTENT => true, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed PDO::ATTR_EMULATE_PREPARES => true, - PDO::ATTR_STRINGIFY_FETCHES => true, - ]); + PDO::ATTR_STRINGIFY_FETCHES => true + )); }); }; break; case 'redis': $resource = function () use ($dsnHost, $dsnPort, $dsnPass) { $redis = new Redis(); - @$redis->pconnect($dsnHost, (int) $dsnPort); + @$redis->pconnect($dsnHost, (int)$dsnPort); if ($dsnPass) { $redis->auth($dsnPass); } @@ -747,7 +745,7 @@ $register->set('pools', function () { break; default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'); + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"); break; } @@ -781,7 +779,7 @@ $register->set('pools', function () { break; default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Server error: Missing adapter implementation.'); + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); break; } @@ -791,7 +789,7 @@ $register->set('pools', function () { $group->add($pool); } - Config::setParam('pools-'.$key, $config); + Config::setParam('pools-' . $key, $config); } return $group; @@ -808,14 +806,14 @@ $register->set('smtp', function () { $mail->XMailer = 'Appwrite Mailer'; $mail->Host = App::getEnv('_APP_SMTP_HOST', 'smtp'); $mail->Port = App::getEnv('_APP_SMTP_PORT', 25); - $mail->SMTPAuth = (! empty($username) && ! empty($password)); + $mail->SMTPAuth = (!empty($username) && !empty($password)); $mail->Username = $username; $mail->Password = $password; $mail->SMTPSecure = App::getEnv('_APP_SMTP_SECURE', false); $mail->SMTPAutoTLS = false; $mail->CharSet = 'UTF-8'; - $from = \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')); + $from = \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); $email = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $mail->setFrom($email, $from); @@ -826,13 +824,12 @@ $register->set('smtp', function () { return $mail; }); $register->set('geodb', function () { - return new Reader(__DIR__.'/assets/dbip/dbip-country-lite-2023-01.mmdb'); + return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2023-01.mmdb'); }); $register->set('passwordsDictionary', function () { - $content = \file_get_contents(__DIR__.'/assets/security/10k-common-passwords'); + $content = \file_get_contents(__DIR__ . '/assets/security/10k-common-passwords'); $content = explode("\n", $content); $content = array_flip($content); - return $content; }); $register->set('promiseAdapter', function () { @@ -848,12 +845,12 @@ $locales = Config::getParam('locale-codes', []); foreach ($locales as $locale) { $code = $locale['code']; - $path = __DIR__.'/config/locale/translations/'.$code.'.json'; + $path = __DIR__ . '/config/locale/translations/' . $code . '.json'; - if (! \file_exists($path)) { - $path = __DIR__.'/config/locale/translations/'.\substr($code, 0, 2).'.json'; // if `ar-ae` doesn't exist, look for `ar` - if (! \file_exists($path)) { - $path = __DIR__.'/config/locale/translations/en.json'; // if none translation exists, use default from `en.json` + if (!\file_exists($path)) { + $path = __DIR__ . '/config/locale/translations/' . \substr($code, 0, 2) . '.json'; // if `ar-ae` doesn't exist, look for `ar` + if (!\file_exists($path)) { + $path = __DIR__ . '/config/locale/translations/en.json'; // if none translation exists, use default from `en.json` } } @@ -881,20 +878,20 @@ App::setResource('loggerBreadcrumbs', function () { return []; }); -App::setResource('register', fn () => $register); -App::setResource('locale', fn () => new Locale(App::getEnv('_APP_LOCALE', 'en'))); +App::setResource('register', fn() => $register); +App::setResource('locale', fn() => new Locale(App::getEnv('_APP_LOCALE', 'en'))); App::setResource('localeCodes', function () { - return array_map(fn ($locale) => $locale['code'], Config::getParam('locale-codes', [])); + return array_map(fn($locale) => $locale['code'], Config::getParam('locale-codes', [])); }); // Queues -App::setResource('events', fn () => new Event('', '')); -App::setResource('audits', fn () => new Audit()); -App::setResource('mails', fn () => new Mail()); -App::setResource('deletes', fn () => new Delete()); -App::setResource('database', fn () => new EventDatabase()); -App::setResource('messaging', fn () => new Phone()); +App::setResource('events', fn() => new Event('', '')); +App::setResource('audits', fn() => new Audit()); +App::setResource('mails', fn() => new Mail()); +App::setResource('deletes', fn() => new Delete()); +App::setResource('database', fn() => new EventDatabase()); +App::setResource('messaging', fn() => new Phone()); App::setResource('queue', function (Group $pools) { return $pools->get('queue')->pop()->getResource(); }, ['pools']); @@ -920,7 +917,7 @@ App::setResource('clients', function ($request, $console, $project) { fn ($node) => $node['hostname'], \array_filter( $console->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && ! empty($node['hostname'])) + fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname'])) ) ); @@ -931,7 +928,7 @@ App::setResource('clients', function ($request, $console, $project) { fn ($node) => $node['hostname'], \array_filter( $project->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && ! empty($node['hostname'])) + fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname'])) ) ) ) @@ -947,22 +944,23 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons /** @var Utopia\Database\Database $dbForProject */ /** @var Utopia\Database\Database $dbForConsole */ /** @var string $mode */ + Authorization::setDefaultStatus(true); - Auth::setCookieName('a_session_'.$project->getId()); + Auth::setCookieName('a_session_' . $project->getId()); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; if (APP_MODE_ADMIN === $mode) { - Auth::setCookieName('a_session_'.$console->getId()); + Auth::setCookieName('a_session_' . $console->getId()); $authDuration = Auth::TOKEN_EXPIRATION_LOGIN_LONG; } $session = Auth::decodeSession( $request->getCookie( Auth::$cookieName, // Get sessions - $request->getCookie(Auth::$cookieName.'_legacy', '') + $request->getCookie(Auth::$cookieName . '_legacy', '') ) - ); // Get fallback session from old clients (no SameSite support) + );// Get fallback session from old clients (no SameSite support) // Get fallback session from clients who block 3rd-party cookies if ($response) { @@ -993,7 +991,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons if ( $user->isEmpty() // Check a document has been found in the DB - || ! Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) + || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) ) { // Validate user has valid login token $user = new Document([]); } @@ -1008,13 +1006,13 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $authJWT = $request->getHeader('x-appwrite-jwt', ''); - if (! empty($authJWT) && ! $project->isEmpty()) { // JWT authentication + if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication $jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway. try { $payload = $jwt->decode($authJWT); } catch (JWTException $error) { - throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. '.$error->getMessage()); + throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage()); } $jwtUserId = $payload['userId'] ?? ''; @@ -1036,13 +1034,14 @@ App::setResource('project', function ($dbForConsole, $request, $console) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForConsole */ /** @var Utopia\Database\Document $console */ + $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); if (empty($projectId) || $projectId === 'console') { return $console; } - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $project = Authorization::skip(fn() => $dbForConsole->getDocument('projects', $projectId)); return $project; }, ['dbForConsole', 'request', 'console']); @@ -1077,12 +1076,12 @@ App::setResource('console', function () { 'limit' => (App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds ], - 'authWhitelistEmails' => (! empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], - 'authWhitelistIPs' => (! empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], + 'authWhitelistEmails' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], + 'authWhitelistIPs' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], 'authProviders' => [ 'githubEnabled' => true, 'githubSecret' => App::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''), - 'githubAppid' => App::getEnv('_APP_CONSOLE_GITHUB_APP_ID', ''), + 'githubAppid' => App::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '') ], ]); }, []); @@ -1095,10 +1094,11 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, $dbAdapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource(); + ->getResource() + ; $database = new Database($dbAdapter, $cache); - $database->setNamespace('_'.$project->getInternalId()); + $database->setNamespace('_' . $project->getInternalId()); return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); @@ -1107,7 +1107,8 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) { $dbAdapter = $pools ->get('console') ->pop() - ->getResource(); + ->getResource() + ; $database = new Database($dbAdapter, $cache); @@ -1124,7 +1125,8 @@ App::setResource('cache', function (Group $pools) { $adapters[] = $pools ->get($value) ->pop() - ->getResource(); + ->getResource() + ; } return new Cache(new Sharding($adapters)); @@ -1135,15 +1137,15 @@ App::setResource('deviceLocal', function () { }); App::setResource('deviceFiles', function ($project) { - return getDevice(APP_STORAGE_UPLOADS.'/app-'.$project->getId()); + return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); }, ['project']); App::setResource('deviceFunctions', function ($project) { - return getDevice(APP_STORAGE_FUNCTIONS.'/app-'.$project->getId()); + return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); }, ['project']); App::setResource('deviceBuilds', function ($project) { - return getDevice(APP_STORAGE_BUILDS.'/app-'.$project->getId()); + return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); }, ['project']); function getDevice($root): Device @@ -1165,7 +1167,7 @@ function getDevice($root): Device $bucket = $dsn->getPath(); $region = $dsn->getParam('region'); } catch (\Exception $e) { - Console::error($e->getMessage().'Invalid DSN. Defaulting to Local device.'); + Console::error($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); } switch ($device) { @@ -1238,6 +1240,7 @@ App::setResource('promiseAdapter', function ($register) { }, ['register']); App::setResource('schema', function ($utopia, $dbForProject) { + $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); $query = Query::getByType($queries, [Query::TYPE_LIMIT])[0] ?? null; @@ -1247,7 +1250,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { }; $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ + $attrs = Authorization::skip(fn() => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -1277,7 +1280,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { $params = [ 'list' => function (string $databaseId, string $collectionId, array $args) { - return ['queries' => $args['queries']]; + return [ 'queries' => $args['queries']]; }, 'create' => function (string $databaseId, string $collectionId, array $args) { $id = $args['id'] ?? 'unique()'; @@ -1325,21 +1328,18 @@ App::setResource('schema', function ($utopia, $dbForProject) { App::setResource('contributors', function () { $path = 'app/config/cloud/contributors.json'; $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; - return $list; }, []); App::setResource('employees', function () { $path = 'app/config/cloud/employees.json'; $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; - return $list; }, []); App::setResource('heroes', function () { $path = 'app/config/cloud/heroes.json'; $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; - return $list; }, []); @@ -1347,13 +1347,12 @@ App::setResource('requestTimestamp', function ($request) { //TODO: Move this to the Request class itself $timestampHeader = $request->getHeader('x-appwrite-timestamp'); $requestTimestamp = null; - if (! empty($timestampHeader)) { + if (!empty($timestampHeader)) { try { $requestTimestamp = new \DateTime($timestampHeader); } catch (\Throwable $e) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid X-Appwrite-Timestamp header value'); } } - return $requestTimestamp; }, ['request']); diff --git a/app/preload.php b/app/preload.php index cec44d4a7d..e587bfaed5 100644 --- a/app/preload.php +++ b/app/preload.php @@ -5,36 +5,38 @@ * * Inializes both Appwrite API entry point, queue workers, and CLI tasks. * Set configuration, framework resources, app constants + * */ + ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); -if (file_exists(__DIR__.'/../vendor/autoload.php')) { - require __DIR__.'/../vendor/autoload.php'; +if (file_exists(__DIR__ . '/../vendor/autoload.php')) { + require __DIR__ . '/../vendor/autoload.php'; } use Utopia\Preloader\Preloader; -include __DIR__.'/controllers/general.php'; +include __DIR__ . '/controllers/general.php'; $preloader = new Preloader(); foreach ( [ - realpath(__DIR__.'/../vendor/composer'), - realpath(__DIR__.'/../vendor/amphp'), - realpath(__DIR__.'/../vendor/felixfbecker'), - realpath(__DIR__.'/../vendor/twig/twig'), - realpath(__DIR__.'/../vendor/guzzlehttp/guzzle'), - realpath(__DIR__.'/../vendor/slickdeals'), - realpath(__DIR__.'/../vendor/psr/log'), - realpath(__DIR__.'/../vendor/matomo'), - realpath(__DIR__.'/../vendor/symfony'), - realpath(__DIR__.'/../vendor/mongodb'), - realpath(__DIR__.'/../vendor/utopia-php/websocket'), // TODO: remove workerman autoload - realpath(__DIR__.'/../vendor/utopia-php/cache'), // TODO: remove memcached autoload - realpath(__DIR__.'/../vendor/utopia-php/queue/src/Queue/Adapter/Workerman.php'), // TODO: remove workerman autoload + realpath(__DIR__ . '/../vendor/composer'), + realpath(__DIR__ . '/../vendor/amphp'), + realpath(__DIR__ . '/../vendor/felixfbecker'), + realpath(__DIR__ . '/../vendor/twig/twig'), + realpath(__DIR__ . '/../vendor/guzzlehttp/guzzle'), + realpath(__DIR__ . '/../vendor/slickdeals'), + realpath(__DIR__ . '/../vendor/psr/log'), + realpath(__DIR__ . '/../vendor/matomo'), + realpath(__DIR__ . '/../vendor/symfony'), + realpath(__DIR__ . '/../vendor/mongodb'), + realpath(__DIR__ . '/../vendor/utopia-php/websocket'), // TODO: remove workerman autoload + realpath(__DIR__ . '/../vendor/utopia-php/cache'), // TODO: remove memcached autoload + realpath(__DIR__ . '/../vendor/utopia-php/queue/src/Queue/Adapter/Workerman.php'), // TODO: remove workerman autoload ] as $key => $value ) { if ($value !== false) { @@ -43,7 +45,7 @@ foreach ( } $preloader - ->paths(realpath(__DIR__.'/../app/config')) - ->paths(realpath(__DIR__.'/../app/controllers')) - ->paths(realpath(__DIR__.'/../src')) + ->paths(realpath(__DIR__ . '/../app/config')) + ->paths(realpath(__DIR__ . '/../app/controllers')) + ->paths(realpath(__DIR__ . '/../src')) ->load(); diff --git a/app/realtime.php b/app/realtime.php index 24def0ec61..772eee49d6 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -3,7 +3,6 @@ use Appwrite\Auth\Auth; use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Network\Validator\Origin; -use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; @@ -13,22 +12,23 @@ use Swoole\Timer; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; -use Utopia\Cache\Adapter\Sharding; -use Utopia\Cache\Cache; use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\Logger\Log; +use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Logger\Log; -use Utopia\WebSocket\Adapter; +use Appwrite\Utopia\Request; +use Utopia\Cache\Adapter\Sharding; +use Utopia\Cache\Cache; +use Utopia\Config\Config; +use Utopia\Database\Database; use Utopia\WebSocket\Server; +use Utopia\WebSocket\Adapter; -require_once __DIR__.'/init.php'; +require_once __DIR__ . '/init.php'; Runtime::enableCoroutine(SWOOLE_HOOK_ALL); @@ -42,7 +42,8 @@ function getConsoleDB(): Database $dbAdapter = $pools ->get('console') ->pop() - ->getResource(); + ->getResource() + ; $database = new Database($dbAdapter, getCache()); @@ -65,10 +66,11 @@ function getProjectDB(Document $project): Database $dbAdapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource(); + ->getResource() + ; $database = new Database($dbAdapter, getCache()); - $database->setNamespace('_'.$project->getInternalId()); + $database->setNamespace('_' . $project->getInternalId()); return $database; } @@ -78,6 +80,7 @@ function getCache(): Cache global $register; $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ + $list = Config::getParam('pools-cache', []); $adapters = []; @@ -85,7 +88,8 @@ function getCache(): Cache $adapters[] = $pools ->get($value) ->pop() - ->getResource(); + ->getResource() + ; } return new Cache(new Sharding($adapters)); @@ -122,7 +126,7 @@ $logError = function (Throwable $error, string $action) use ($register) { $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $log = new Log(); - $log->setNamespace('realtime'); + $log->setNamespace("realtime"); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); @@ -142,13 +146,13 @@ $logError = function (Throwable $error, string $action) use ($register) { $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('Realtime log pushed with status code: '.$responseCode); + Console::info('Realtime log pushed with status code: ' . $responseCode); } - Console::error('[Error] Type: '.get_class($error)); - Console::error('[Error] Message: '.$error->getMessage()); - Console::error('[Error] File: '.$error->getFile()); - Console::error('[Error] Line: '.$error->getLine()); + Console::error('[Error] Type: ' . get_class($error)); + Console::error('[Error] Message: ' . $error->getMessage()); + Console::error('[Error] File: ' . $error->getFile()); + Console::error('[Error] Line: ' . $error->getLine()); }; $server->error($logError); @@ -173,7 +177,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume '$permissions' => [], 'container' => $containerId, 'timestamp' => DateTime::now(), - 'value' => '{}', + 'value' => '{}' ]); $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); @@ -207,7 +211,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (\Throwable $th) { - call_user_func($logError, $th, 'updateWorkerDocument'); + call_user_func($logError, $th, "updateWorkerDocument"); } finally { $register->get('pools')->reclaim(); } @@ -215,12 +219,12 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume }); $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime, $logError) { - Console::success('Worker '.$workerId.' started successfully'); + Console::success('Worker ' . $workerId . ' started successfully'); $attempts = 0; $start = time(); - Timer::tick(5000, function () use ($server, $register, $realtime, $stats) { + Timer::tick(5000, function () use ($server, $register, $realtime, $stats, $logError) { /** * Sending current connections to project channels on the console project every 5 seconds. */ @@ -239,34 +243,34 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, foreach ($list as $document) { foreach (json_decode($document->getAttribute('value')) as $projectId => $value) { if (array_key_exists($projectId, $payload)) { - $payload[$projectId] += $value; + $payload[$projectId] += $value; } else { - $payload[$projectId] = $value; + $payload[$projectId] = $value; } } } foreach ($stats as $projectId => $value) { - if (! array_key_exists($projectId, $payload)) { + if (!array_key_exists($projectId, $payload)) { continue; } $event = [ 'project' => 'console', - 'roles' => ['team:'.$stats->get($projectId, 'teamId')], + 'roles' => ['team:' . $stats->get($projectId, 'teamId')], 'data' => [ 'events' => ['stats.connections'], 'channels' => ['project'], 'timestamp' => DateTime::formatTz(DateTime::now()), 'payload' => [ - $projectId => $payload[$projectId], - ], - ], + $projectId => $payload[$projectId] + ] + ] ]; $server->send($realtime->getSubscribers($event), json_encode([ 'type' => 'event', - 'data' => $event['data'], + 'data' => $event['data'] ])); } @@ -285,13 +289,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, 'events' => ['test.event'], 'channels' => ['tests'], 'timestamp' => DateTime::formatTz(DateTime::now()), - 'payload' => $payload, - ], + 'payload' => $payload + ] ]; $server->send($realtime->getSubscribers($event), json_encode([ 'type' => 'event', - 'data' => $event['data'], + 'data' => $event['data'] ])); } }); @@ -299,8 +303,8 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, while ($attempts < 300) { try { if ($attempts > 0) { - Console::error('Pub/sub connection lost (lasted '.(time() - $start).' seconds, worker: '.$workerId.'). - Attempting restart in 5 seconds (attempt #'.$attempts.')'); + Console::error('Pub/sub connection lost (lasted ' . (time() - $start) . ' seconds, worker: ' . $workerId . '). + Attempting restart in 5 seconds (attempt #' . $attempts . ')'); sleep(5); // 5 sec delay between connection attempts } $start = time(); @@ -310,9 +314,9 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, if ($redis->ping(true)) { $attempts = 0; - Console::success('Pub/sub connection established (worker: '.$workerId.')'); + Console::success('Pub/sub connection established (worker: ' . $workerId . ')'); } else { - Console::error('Pub/sub failed (worker: '.$workerId.')'); + Console::error('Pub/sub failed (worker: ' . $workerId . ')'); } $redis->subscribe(['realtime'], function (Redis $redis, string $channel, string $payload) use ($server, $workerId, $stats, $register, $realtime) { @@ -322,10 +326,10 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $projectId = $event['project']; $userId = $event['userId']; - if ($realtime->hasSubscriber($projectId, 'user:'.$userId)) { - $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:'.$userId])); + if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) { + $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId])); $consoleDatabase = getConsoleDB(); - $project = Authorization::skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); + $project = Authorization::skip(fn() => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); $user = $database->getDocument('users', $userId); @@ -340,17 +344,17 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $receivers = $realtime->getSubscribers($event); - if (App::isDevelopment() && ! empty($receivers)) { - Console::log("[Debug][Worker {$workerId}] Receivers: ".count($receivers)); - Console::log("[Debug][Worker {$workerId}] Receivers Connection IDs: ".json_encode($receivers)); - Console::log("[Debug][Worker {$workerId}] Event: ".$payload); + if (App::isDevelopment() && !empty($receivers)) { + Console::log("[Debug][Worker {$workerId}] Receivers: " . count($receivers)); + Console::log("[Debug][Worker {$workerId}] Receivers Connection IDs: " . json_encode($receivers)); + Console::log("[Debug][Worker {$workerId}] Event: " . $payload); } $server->send( $receivers, json_encode([ 'type' => 'event', - 'data' => $event['data'], + 'data' => $event['data'] ]) ); @@ -359,12 +363,11 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, } }); } catch (\Throwable $th) { - call_user_func($logError, $th, 'pubSubConnection'); + call_user_func($logError, $th, "pubSubConnection"); - Console::error('Pub/sub error: '.$th->getMessage()); + Console::error('Pub/sub error: ' . $th->getMessage()); $attempts++; sleep(DATABASE_RECONNECT_SLEEP); - continue; } finally { $register->get('pools')->reclaim(); @@ -381,9 +384,9 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, Console::info("Connection open (user: {$connection})"); - App::setResource('pools', fn () => $register->get('pools')); - App::setResource('request', fn () => $request); - App::setResource('response', fn () => $response); + App::setResource('pools', fn() => $register->get('pools')); + App::setResource('request', fn() => $request); + App::setResource('response', fn() => $response); try { /** @var \Utopia\Database\Document $project */ @@ -424,7 +427,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $origin = $request->getOrigin(); $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); - if (! $originValidator->isValid($origin) && $project->getId() !== 'console') { + if (!$originValidator->isValid($origin) && $project->getId() !== 'console') { throw new Exception($originValidator->getDescription(), 1008); } @@ -447,25 +450,25 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, 'type' => 'connected', 'data' => [ 'channels' => array_keys($channels), - 'user' => $user, - ], + 'user' => $user + ] ])); $stats->set($project->getId(), [ 'projectId' => $project->getId(), - 'teamId' => $project->getAttribute('teamId'), + 'teamId' => $project->getAttribute('teamId') ]); $stats->incr($project->getId(), 'connections'); $stats->incr($project->getId(), 'connectionsTotal'); } catch (\Throwable $th) { - call_user_func($logError, $th, 'initServer'); + call_user_func($logError, $th, "initServer"); $response = [ 'type' => 'error', 'data' => [ 'code' => $th->getCode(), - 'message' => $th->getMessage(), - ], + 'message' => $th->getMessage() + ] ]; $server->send([$connection], json_encode($response)); @@ -473,8 +476,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if (App::isDevelopment()) { Console::error('[Error] Connection Error'); - Console::error('[Error] Code: '.$response['data']['code']); - Console::error('[Error] Message: '.$response['data']['message']); + Console::error('[Error] Code: ' . $response['data']['code']); + Console::error('[Error] Message: ' . $response['data']['message']); } } finally { $register->get('pools')->reclaim(); @@ -489,7 +492,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $database = getConsoleDB(); if ($projectId !== 'console') { - $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); + $project = Authorization::skip(fn() => $database->getDocument('projects', $projectId)); $database = getProjectDB($project); } @@ -512,16 +515,16 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $message = json_decode($message, true); - if (is_null($message) || (! array_key_exists('type', $message) && ! array_key_exists('data', $message))) { + if (is_null($message) || (!array_key_exists('type', $message) && !array_key_exists('data', $message))) { throw new Exception('Message format is not valid.', 1003); } switch ($message['type']) { - /** + /** * This type is used to authenticate. */ case 'authentication': - if (! array_key_exists('session', $message['data'])) { + if (!array_key_exists('session', $message['data'])) { throw new Exception('Payload is not valid.', 1003); } @@ -534,7 +537,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re if ( empty($user->getId()) // Check a document has been found in the DB - || ! Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) // Validate user has valid login token + || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) // Validate user has valid login token ) { // cookie not valid throw new Exception('Session is not valid.', 1003); @@ -550,8 +553,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re 'data' => [ 'to' => 'authentication', 'success' => true, - 'user' => $user, - ], + 'user' => $user + ] ])); break; @@ -564,8 +567,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re 'type' => 'error', 'data' => [ 'code' => $th->getCode(), - 'message' => $th->getMessage(), - ], + 'message' => $th->getMessage() + ] ]; $server->send([$connection], json_encode($response)); @@ -584,7 +587,7 @@ $server->onClose(function (int $connection) use ($realtime, $stats) { } $realtime->unsubscribe($connection); - Console::info('Connection close: '.$connection); + Console::info('Connection close: ' . $connection); }); $server->start(); diff --git a/app/worker.php b/app/worker.php index bd7cf7970d..ea086fa43d 100644 --- a/app/worker.php +++ b/app/worker.php @@ -1,6 +1,6 @@ $register); +Server::setResource('register', fn() => $register); Server::setResource('dbForConsole', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); $database = $pools ->get('console') ->pop() - ->getResource(); + ->getResource() + ; $adapter = new Database($database, $cache); $adapter->setNamespace('console'); @@ -51,11 +52,11 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource(); + ->getResource() + ; $adapter = new Database($database, $cache); - $adapter->setNamespace('_'.$project->getInternalId()); - + $adapter->setNamespace('_' . $project->getInternalId()); return $adapter; }, ['cache', 'register', 'message', 'dbForConsole']); @@ -68,7 +69,8 @@ Server::setResource('cache', function (Registry $register) { $adapters[] = $pools ->get($value) ->pop() - ->getResource(); + ->getResource() + ; } return new Cache(new Sharding($adapters)); @@ -76,7 +78,6 @@ Server::setResource('cache', function (Registry $register) { Server::setResource('queueForFunctions', function (Registry $register) { $pools = $register->get('pools'); - return new Func( $pools ->get('queue') @@ -87,7 +88,6 @@ Server::setResource('queueForFunctions', function (Registry $register) { Server::setResource('queueForUsage', function (Registry $register) { $pools = $register->get('pools'); - return new Usage( $pools ->get('queue') @@ -96,7 +96,7 @@ Server::setResource('queueForUsage', function (Registry $register) { ); }, ['register']); -Server::setResource('log', fn () => new Log()); +Server::setResource('log', fn() => new Log()); Server::setResource('logger', function ($register) { return $register->get('logger'); @@ -137,12 +137,12 @@ $server } if ($logger && ($error->getCode() >= 500 || $error->getCode() === 0)) { - $log->setNamespace('appwrite-worker'); + $log->setNamespace("appwrite-worker"); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); - $log->setAction('appwrite-queue-'.App::getEnv('QUEUE')); + $log->setAction('appwrite-queue-' . App::getEnv('QUEUE')); $log->addTag('verboseType', get_class($error)); $log->addTag('code', $error->getCode()); $log->addExtra('file', $error->getFile()); @@ -155,11 +155,11 @@ $server $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); $responseCode = $logger->addLog($log); - Console::info('Usage stats log pushed with status code: '.$responseCode); + Console::info('Usage stats log pushed with status code: ' . $responseCode); } - Console::error('[Error] Type: '.get_class($error)); - Console::error('[Error] Message: '.$error->getMessage()); - Console::error('[Error] File: '.$error->getFile()); - Console::error('[Error] Line: '.$error->getLine()); + Console::error('[Error] Type: ' . get_class($error)); + Console::error('[Error] Message: ' . $error->getMessage()); + Console::error('[Error] File: ' . $error->getFile()); + Console::error('[Error] Line: ' . $error->getLine()); }); diff --git a/app/workers/audits.php b/app/workers/audits.php index a304fd70bb..8369ec74ec 100644 --- a/app/workers/audits.php +++ b/app/workers/audits.php @@ -5,16 +5,16 @@ use Utopia\Audit\Audit; use Utopia\CLI\Console; use Utopia\Database\Document; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Audits V1 Worker'); -Console::success(APP_NAME.' audits worker v1 has started'); +Console::success(APP_NAME . ' audits worker v1 has started'); class AuditsV1 extends Worker { public function getName(): string { - return 'audits'; + return "audits"; } public function init(): void diff --git a/app/workers/builds.php b/app/workers/builds.php index 41c3cbdcc7..972eb5dd18 100644 --- a/app/workers/builds.php +++ b/app/workers/builds.php @@ -6,20 +6,20 @@ use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Resque\Worker; use Appwrite\Utopia\Response\Model\Deployment; use Executor\Executor; +use Utopia\Database\DateTime; use Utopia\App; use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Database\DateTime; -use Utopia\Database\Document; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; +use Utopia\Database\Document; +use Utopia\Config\Config; +use Utopia\Database\Validator\Authorization; use Utopia\Storage\Storage; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Builds V1 Worker'); -Console::success(APP_NAME.' build worker v1 has started'); +Console::success(APP_NAME . ' build worker v1 has started'); // TODO: Executor should return appropriate response codes. class BuildsV1 extends Worker @@ -28,7 +28,7 @@ class BuildsV1 extends Worker public function getName(): string { - return 'builds'; + return "builds"; } public function init(): void @@ -46,7 +46,7 @@ class BuildsV1 extends Worker switch ($type) { case BUILD_TYPE_DEPLOYMENT: case BUILD_TYPE_RETRY: - Console::info('Creating build for deployment: '.$deployment->getId()); + Console::info('Creating build for deployment: ' . $deployment->getId()); $this->buildDeployment($project, $resource, $deployment); break; @@ -81,7 +81,7 @@ class BuildsV1 extends Worker $key = $function->getAttribute('runtime'); $runtime = isset($runtimes[$key]) ? $runtimes[$key] : null; if (\is_null($runtime)) { - throw new Exception('Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); + throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } $connection = App::getEnv('_APP_CONNECTIONS_STORAGE', ''); /** @TODO : move this to the registry or someplace else */ @@ -90,7 +90,7 @@ class BuildsV1 extends Worker $dsn = new DSN($connection); $device = $dsn->getScheme(); } catch (\Exception $e) { - Console::error($e->getMessage().'Invalid DSN. Defaulting to Local device.'); + Console::error($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); } $buildId = $deployment->getAttribute('buildId', ''); @@ -111,7 +111,7 @@ class BuildsV1 extends Worker 'stdout' => '', 'stderr' => '', 'endTime' => null, - 'duration' => 0, + 'duration' => 0 ])); $deployment->setAttribute('buildId', $build->getId()); $deployment->setAttribute('buildInternalId', $build->getInternalId()); @@ -150,7 +150,7 @@ class BuildsV1 extends Worker /** Trigger Realtime */ $allEvents = Event::generateEvents('functions.[functionId].deployments.[deploymentId].update', [ 'functionId' => $function->getId(), - 'deploymentId' => $deployment->getId(), + 'deploymentId' => $deployment->getId() ]); $target = Realtime::fromPayload( // Pass first, most verbose event pattern @@ -171,7 +171,6 @@ class BuildsV1 extends Worker $vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) { $carry[$var->getAttribute('key')] = $var->getAttribute('value'); - return $carry; }, []); @@ -184,12 +183,12 @@ class BuildsV1 extends Worker remove: true, entrypoint: $deployment->getAttribute('entrypoint'), workdir: '/usr/code', - destination: APP_STORAGE_BUILDS."/app-{$project->getId()}", + destination: APP_STORAGE_BUILDS . "/app-{$project->getId()}", variables: $vars, commands: [ 'sh', '-c', 'tar -zxf /tmp/code.tar.gz -C /usr/code && \ - cd /usr/local/src/ && ./build.sh', + cd /usr/local/src/ && ./build.sh' ] ); @@ -223,7 +222,8 @@ class BuildsV1 extends Worker $schedule ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment'))); + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); + Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); } catch (\Throwable $th) { @@ -261,11 +261,12 @@ class BuildsV1 extends Worker ->setProject($project) ->addMetric(METRIC_BUILDS, 1) // per project ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) - ->addMetric(METRIC_BUILDS_COMPUTE, (int) $build->getAttribute('duration', 0) * 1000) + ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int) $build->getAttribute('duration', 0) * 1000) - ->trigger(); + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) + ->trigger() + ; } public function shutdown(): void diff --git a/app/workers/certificates.php b/app/workers/certificates.php index fc72f6d4e6..824a296b75 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -7,17 +7,17 @@ use Appwrite\Template\Template; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Domains\Domain; use Utopia\Locale\Locale; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Certificates V1 Worker'); -Console::success(APP_NAME.' certificates worker v1 has started'); +Console::success(APP_NAME . ' certificates worker v1 has started'); class CertificatesV1 extends Worker { @@ -30,7 +30,7 @@ class CertificatesV1 extends Worker public function getName(): string { - return 'certificates'; + return "certificates"; } public function init(): void @@ -68,6 +68,7 @@ class CertificatesV1 extends Worker * * Note: Renewals are checked and scheduled from maintenence worker */ + $this->dbForConsole = $this->getConsoleDB(); $skipCheck = $this->args['skipRenewCheck'] ?? false; // If true, we won't double-check expiry from cert file @@ -78,7 +79,7 @@ class CertificatesV1 extends Worker $certificate = $this->dbForConsole->findOne('certificates', [Query::equal('domain', [$domain->get()])]); // If we don't have certificate for domain yet, let's create new document. At the end we save it - if (! $certificate) { + if (!$certificate) { $certificate = new Document(); $certificate->setAttribute('domain', $domain->get()); } @@ -91,14 +92,14 @@ class CertificatesV1 extends Worker } // Validate domain and DNS records. Skip if job is forced - if (! $skipCheck) { + if (!$skipCheck) { $mainDomain = $this->getMainDomain(); - $isMainDomain = ! isset($mainDomain) || $domain->get() === $mainDomain; + $isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain; $this->validateDomain($domain, $isMainDomain); } // If certificate exists already, double-check expiry date. Skip if job is forced - if (! $skipCheck && ! $this->isRenewRequired($domain->get())) { + if (!$skipCheck && !$this->isRenewRequired($domain->get())) { throw new Exception('Renew isn\'t required.'); } @@ -151,15 +152,16 @@ class CertificatesV1 extends Worker /** * Save certificate data into database. * - * @param string $domain Domain name that certificate is for - * @param Document $certificate Certificate document that we need to save + * @param string $domain Domain name that certificate is for + * @param Document $certificate Certificate document that we need to save + * * @return void */ private function saveCertificateDocument(string $domain, Document $certificate): void { // Check if update or insert required $certificateDocument = $this->dbForConsole->findOne('certificates', [Query::equal('domain', [$domain])]); - if (! empty($certificateDocument) && ! $certificateDocument->isEmpty()) { + if (!empty($certificateDocument) && !$certificateDocument->isEmpty()) { // Merge new data with current data $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); @@ -180,7 +182,7 @@ class CertificatesV1 extends Worker private function getMainDomain(): ?string { $envDomain = App::getEnv('_APP_DOMAIN', ''); - if (! empty($envDomain) && $envDomain !== 'localhost') { + if (!empty($envDomain) && $envDomain !== 'localhost') { return $envDomain; } else { $domainDocument = $this->dbForConsole->findOne('domains', [Query::orderAsc('_id')]); @@ -197,8 +199,9 @@ class CertificatesV1 extends Worker * - Domain needs to be public and valid (prevents NFT domains that are not supported by Let's Encrypt) * - Domain must have proper DNS record * - * @param Domain $domain Domain which we validate - * @param bool $isMainDomain In case of master domain, we look for different DNS configurations + * @param Domain $domain Domain which we validate + * @param bool $isMainDomain In case of master domain, we look for different DNS configurations + * * @return void */ private function validateDomain(Domain $domain, bool $isMainDomain): void @@ -207,23 +210,23 @@ class CertificatesV1 extends Worker throw new Exception('Missing certificate domain.'); } - if (! $domain->isKnown() || $domain->isTest()) { + if (!$domain->isKnown() || $domain->isTest()) { throw new Exception('Unknown public suffix for domain.'); } - if (! $isMainDomain) { + if (!$isMainDomain) { // TODO: Would be awesome to also support A/AAAA records here. Maybe dry run? // Validate if domain target is properly configured $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - if (! $target->isKnown() || $target->isTest()) { - throw new Exception('Unreachable CNAME target ('.$target->get().'), please use a domain with a public suffix.'); + if (!$target->isKnown() || $target->isTest()) { + throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.'); } // Verify domain with DNS records $validator = new CNAME($target->get()); - if (! $validator->isValid($domain->get())) { + if (!$validator->isValid($domain->get())) { throw new Exception('Failed to verify domain DNS records.'); } } else { @@ -235,12 +238,13 @@ class CertificatesV1 extends Worker /** * Reads expiry date of certificate from file and decides if renewal is required or not. * - * @param string $domain Domain for which we check certificate file + * @param string $domain Domain for which we check certificate file + * * @return bool True, if certificate needs to be renewed */ private function isRenewRequired(string $domain): bool { - $certPath = APP_STORAGE_CERTIFICATES.'/'.$domain.'/cert.pem'; + $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; if (\file_exists($certPath)) { $validTo = null; @@ -264,8 +268,9 @@ class CertificatesV1 extends Worker /** * LetsEncrypt communication to issue certificate (using certbot CLI) * - * @param string $folder Folder into which certificates should be generated - * @param string $domain Domain to generate certificate for + * @param string $folder Folder into which certificates should be generated + * @param string $domain Domain to generate certificate for + * * @return array Named array with keys 'stdout' and 'stderr', both string */ private function issueCertificate(string $folder, string $domain, string $email): array @@ -275,82 +280,83 @@ class CertificatesV1 extends Worker $staging = (App::isProduction()) ? '' : ' --dry-run'; $exit = Console::execute("certbot certonly --webroot --noninteractive --agree-tos{$staging}" - .' --email '.$email - .' --cert-name '.$folder - .' -w '.APP_STORAGE_CERTIFICATES - ." -d {$domain}", '', $stdout, $stderr); + . " --email " . $email + . " --cert-name " . $folder + . " -w " . APP_STORAGE_CERTIFICATES + . " -d {$domain}", '', $stdout, $stderr); // Unexpected error, usually 5XX, API limits, ... if ($exit !== 0) { - throw new Exception('Failed to issue a certificate with message: '.$stderr); + throw new Exception('Failed to issue a certificate with message: ' . $stderr); } return [ 'stdout' => $stdout, - 'stderr' => $stderr, + 'stderr' => $stderr ]; } /** * Read new renew date from certificate file generated by Let's Encrypt * - * @param string $domain Domain which certificate was generated for + * @param string $domain Domain which certificate was generated for + * * @return string */ private function getRenewDate(string $domain): string { - $certPath = APP_STORAGE_CERTIFICATES.'/'.$domain.'/cert.pem'; + $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; $certData = openssl_x509_parse(file_get_contents($certPath)); $validTo = $certData['validTo_time_t'] ?? null; $dt = (new \DateTime())->setTimestamp($validTo); - return DateTime::addSeconds($dt, -60 * 60 * 24 * 30); // -30 days } /** * Method to take files from Let's Encrypt, and put it into Traefik. * - * @param string $domain Domain which certificate was generated for - * @param string $folder Folder in which certificates were generated - * @param array $letsEncryptData Let's Encrypt logs to use for additional info when throwing error + * @param string $domain Domain which certificate was generated for + * @param string $folder Folder in which certificates were generated + * @param array $letsEncryptData Let's Encrypt logs to use for additional info when throwing error + * * @return void */ private function applyCertificateFiles(string $folder, string $domain, array $letsEncryptData): void { // Prepare folder in storage for domain - $path = APP_STORAGE_CERTIFICATES.'/'.$domain; - if (! \is_readable($path)) { - if (! \mkdir($path, 0755, true)) { + $path = APP_STORAGE_CERTIFICATES . '/' . $domain; + if (!\is_readable($path)) { + if (!\mkdir($path, 0755, true)) { throw new Exception('Failed to create path for certificate.'); } } // Move generated files - if (! @\rename('/etc/letsencrypt/live/'.$folder.'/cert.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/cert.pem')) { - throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); + if (!@\rename('/etc/letsencrypt/live/' . $folder . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) { + throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); } - if (! @\rename('/etc/letsencrypt/live/'.$folder.'/chain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/chain.pem')) { - throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); + if (!@\rename('/etc/letsencrypt/live/' . $folder . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) { + throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); } - if (! @\rename('/etc/letsencrypt/live/'.$folder.'/fullchain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/fullchain.pem')) { - throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); + if (!@\rename('/etc/letsencrypt/live/' . $folder . '/fullchain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/fullchain.pem')) { + throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); } - if (! @\rename('/etc/letsencrypt/live/'.$folder.'/privkey.pem', APP_STORAGE_CERTIFICATES.'/'.$domain.'/privkey.pem')) { - throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: '.$letsEncryptData['stderr'].' ; '.$letsEncryptData['stdout']); + if (!@\rename('/etc/letsencrypt/live/' . $folder . '/privkey.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/privkey.pem')) { + throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); } $config = \implode(PHP_EOL, [ - 'tls:', - ' certificates:', + "tls:", + " certificates:", " - certFile: /storage/certificates/{$domain}/fullchain.pem", - " keyFile: /storage/certificates/{$domain}/privkey.pem", + " keyFile: /storage/certificates/{$domain}/privkey.pem" ]); // Save configuration into Traefik using our new cert files - if (! \file_put_contents(APP_STORAGE_CONFIG.'/'.$domain.'.yml', $config)) { + if (!\file_put_contents(APP_STORAGE_CONFIG . '/' . $domain . '.yml', $config)) { throw new Exception('Failed to save Traefik configuration.'); } } @@ -358,38 +364,39 @@ class CertificatesV1 extends Worker /** * Method to make sure information about error is delivered to admnistrator. * - * @param string $domain Domain that caused the error - * @param string $errorMessage Verbose error message - * @param int $attempt How many times it failed already + * @param string $domain Domain that caused the error + * @param string $errorMessage Verbose error message + * @param int $attempt How many times it failed already + * * @return void */ private function notifyError(string $domain, string $errorMessage, int $attempt): void { // Log error into console - Console::warning('Cannot renew domain ('.$domain.') on attempt no. '.$attempt.' certificate: '.$errorMessage); + Console::warning('Cannot renew domain (' . $domain . ') on attempt no. ' . $attempt . ' certificate: ' . $errorMessage); // Send mail to administratore mail $locale = new Locale(App::getEnv('_APP_LOCALE', 'en')); - if (! $locale->getText('emails.sender') || ! $locale->getText('emails.certificate.hello') || ! $locale->getText('emails.certificate.subject') || ! $locale->getText('emails.certificate.body') || ! $locale->getText('emails.certificate.footer') || ! $locale->getText('emails.certificate.thanks') || ! $locale->getText('emails.certificate.signature')) { + if (!$locale->getText('emails.sender') || !$locale->getText("emails.certificate.hello") || !$locale->getText("emails.certificate.subject") || !$locale->getText("emails.certificate.body") || !$locale->getText("emails.certificate.footer") || !$locale->getText("emails.certificate.thanks") || !$locale->getText("emails.certificate.signature")) { $locale->setDefault('en'); } - $body = Template::fromFile(__DIR__.'/../config/locale/templates/email-base.tpl'); + $body = Template::fromFile(__DIR__ . '/../config/locale/templates/email-base.tpl'); - $subject = \sprintf($locale->getText('emails.certificate.subject'), $domain); - $body->setParam('{{domain}}', $domain); - $body->setParam('{{error}}', $errorMessage); - $body->setParam('{{attempt}}', $attempt); + $subject = \sprintf($locale->getText("emails.certificate.subject"), $domain); + $body->setParam('{{domain}}', $domain); + $body->setParam('{{error}}', $errorMessage); + $body->setParam('{{attempt}}', $attempt); $body ->setParam('{{subject}}', $subject) - ->setParam('{{hello}}', $locale->getText('emails.certificate.hello')) - ->setParam('{{body}}', $locale->getText('emails.certificate.body')) - ->setParam('{{redirect}}', 'https://'.$domain) - ->setParam('{{footer}}', $locale->getText('emails.certificate.footer')) - ->setParam('{{thanks}}', $locale->getText('emails.certificate.thanks')) - ->setParam('{{signature}}', $locale->getText('emails.certificate.signature')) + ->setParam('{{hello}}', $locale->getText("emails.certificate.hello")) + ->setParam('{{body}}', $locale->getText("emails.certificate.body")) + ->setParam('{{redirect}}', 'https://' . $domain) + ->setParam('{{footer}}', $locale->getText("emails.certificate.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.certificate.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.certificate.signature")) ->setParam('{{project}}', 'Console') ->setParam('{{direction}}', $locale->getText('settings.direction')) ->setParam('{{bg-body}}', '#f7f7f7') @@ -411,8 +418,9 @@ class CertificatesV1 extends Worker * - when renew creates new document? It might? * - overall makes it more reliable * - * @param string $certificateId ID of a new or updated certificate document - * @param string $domain Domain that is affected by new certificate + * @param string $certificateId ID of a new or updated certificate document + * @param string $domain Domain that is affected by new certificate + * * @return void */ private function updateDomainDocuments(string $certificateId, string $domain): void diff --git a/app/workers/databases.php b/app/workers/databases.php index 6490c7a8d9..764f668f33 100644 --- a/app/workers/databases.php +++ b/app/workers/databases.php @@ -9,10 +9,10 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Database V1 Worker'); -Console::success(APP_NAME.' database worker v1 has started'."\n"); +Console::success(APP_NAME . ' database worker v1 has started' . "\n"); class DatabaseV1 extends Worker { @@ -51,7 +51,7 @@ class DatabaseV1 extends Worker break; default: - Console::error('No database operation for type: '.$type); + Console::error('No database operation for type: ' . $type); break; } } @@ -61,10 +61,10 @@ class DatabaseV1 extends Worker } /** - * @param Document $database - * @param Document $collection - * @param Document $attribute - * @param Document $project + * @param Document $database + * @param Document $collection + * @param Document $attribute + * @param Document $project */ protected function createAttribute(Document $database, Document $collection, Document $attribute, Document $project): void { @@ -75,7 +75,7 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].update', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'attributeId' => $attribute->getId(), + 'attributeId' => $attribute->getId() ]); /** * Fetch attribute from the database, since with Resque float values are loosing informations. @@ -99,15 +99,15 @@ class DatabaseV1 extends Worker try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedCollection = $dbForProject->getDocument('database_'.$database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } if ( - ! $dbForProject->createRelationship( - collection: 'database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), - relatedCollection: 'database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId(), + !$dbForProject->createRelationship( + collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -119,12 +119,12 @@ class DatabaseV1 extends Worker } if ($options['twoWay']) { - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); } break; default: - if (! $dbForProject->createAttribute('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } } @@ -170,24 +170,23 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), + 'collectionId' => $collection->getId() ] ); } if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { - $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } - $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); } /** - * @param Document $database - * @param Document $collection - * @param Document $attribute - * @param Document $project - * + * @param Document $database + * @param Document $collection + * @param Document $attribute + * @param Document $project * @throws Throwable */ protected function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project): void @@ -199,7 +198,7 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'attributeId' => $attribute->getId(), + 'attributeId' => $attribute->getId() ]); $collectionId = $collection->getId(); $key = $attribute->getAttribute('key', ''); @@ -220,25 +219,25 @@ class DatabaseV1 extends Worker if ($status !== 'failed') { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_'.$database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId().'_'.$relatedCollection->getInternalId().'_'.$options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); } - if (! $dbForProject->deleteRelationship('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key)) { + if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (! $dbForProject->deleteAttribute('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key)) { + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete Attribute'); } } $dbForProject->deleteDocument('attributes', $attribute->getId()); - if (! $relatedAttribute->isEmpty()) { + if (!$relatedAttribute->isEmpty()) { $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } } catch (\Exception $e) { @@ -246,7 +245,7 @@ class DatabaseV1 extends Worker if ($e instanceof DatabaseException) { $attribute->setAttribute('error', $e->getMessage()); - if (! $relatedAttribute->isEmpty()) { + if (!$relatedAttribute->isEmpty()) { $relatedAttribute->setAttribute('error', $e->getMessage()); } } @@ -255,7 +254,7 @@ class DatabaseV1 extends Worker $attribute->getId(), $attribute->setAttribute('status', 'stuck') ); - if (! $relatedAttribute->isEmpty()) { + if (!$relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), @@ -279,7 +278,7 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), + 'collectionId' => $collection->getId() ] ); } @@ -335,21 +334,20 @@ class DatabaseV1 extends Worker } } - $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId()); + $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - if (! $relatedCollection->isEmpty() && ! $relatedAttribute->isEmpty()) { - $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_'.$database->getInternalId().'_collection_'.$relatedCollection->getInternalId()); + if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { + $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } /** - * @param Document $database - * @param Document $collection - * @param Document $index - * @param Document $project - * + * @param Document $database + * @param Document $collection + * @param Document $index + * @param Document $project * @throws \Exception */ protected function createIndex(Document $database, Document $collection, Document $index, Document $project): void @@ -361,7 +359,7 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].update', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'indexId' => $index->getId(), + 'indexId' => $index->getId() ]); $collectionId = $collection->getId(); $key = $index->getAttribute('key', ''); @@ -372,7 +370,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if (! $dbForProject->createIndex('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -404,19 +402,19 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), + 'collectionId' => $collection->getId() ] ); } - $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collectionId); + $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); } /** - * @param Document $database - * @param Document $collection - * @param Document $index - * @param Document $project + * @param Document $database + * @param Document $collection + * @param Document $index + * @param Document $project */ protected function deleteIndex(Document $database, Document $collection, Document $index, Document $project): void { @@ -427,14 +425,14 @@ class DatabaseV1 extends Worker $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].delete', [ 'databaseId' => $database->getId(), 'collectionId' => $collection->getId(), - 'indexId' => $index->getId(), + 'indexId' => $index->getId() ]); $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); $project = $dbForConsole->getDocument('projects', $projectId); try { - if ($status !== 'failed' && ! $dbForProject->deleteIndex('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -466,11 +464,11 @@ class DatabaseV1 extends Worker options: [ 'projectId' => $projectId, 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), + 'collectionId' => $collection->getId() ] ); } - $dbForProject->deleteCachedDocument('database_'.$database->getInternalId(), $collection->getId()); + $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } } diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 7d276f22cf..7f426bf4f4 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -1,29 +1,29 @@ deleteCollection($document, $project); break; } - Console::error('No lazy delete operation available for document of type: '.$document->getCollection()); + Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); break; } break; @@ -82,14 +82,14 @@ class DeletesV1 extends Worker case DELETE_TYPE_AUDIT: $datetime = $this->args['datetime'] ?? null; - if (! empty($datetime)) { + if (!empty($datetime)) { $this->deleteAuditLogs($datetime); } $document = new Document($this->args['document'] ?? []); - if (! $document->isEmpty()) { - $this->deleteAuditLogsByResource('document/'.$document->getId(), $project); + if (!$document->isEmpty()) { + $this->deleteAuditLogsByResource('document/' . $document->getId(), $project); } break; @@ -125,7 +125,7 @@ class DeletesV1 extends Worker $this->deleteSchedules($this->args['datetime']); break; default: - Console::error('No delete operation for type: '.$type); + Console::error('No delete operation for type: ' . $type); break; } } @@ -153,8 +153,7 @@ class DeletesV1 extends Worker if ($project->isEmpty()) { $this->getConsoleDB()->deleteDocument('schedules', $document->getId()); - Console::success('Deleted schedule for deleted project '.$document->getAttribute('projectId')); - + Console::success('Deleted schedule for deleted project ' . $document->getAttribute('projectId')); return; } @@ -162,16 +161,15 @@ class DeletesV1 extends Worker if ($function->isEmpty()) { $this->getConsoleDB()->deleteDocument('schedules', $document->getId()); - Console::success('Deleted schedule for function '.$document->getAttribute('resourceId')); + Console::success('Deleted schedule for function ' . $document->getAttribute('resourceId')); } } ); } /** - * @param Document $project - * @param string $resource - * + * @param Document $project + * @param string $resource * @throws Exception */ protected function deleteCacheByResource(Document $project, string $resource): void @@ -182,19 +180,19 @@ class DeletesV1 extends Worker if ($document) { $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId) + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) ); $this->deleteById( $document, $dbForProject, function ($document) use ($cache, $projectId) { - $path = APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId.DIRECTORY_SEPARATOR.$document->getId(); + $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); if ($cache->purge($document->getId())) { - Console::success('Deleting cache file: '.$path); + Console::success('Deleting cache file: ' . $path); } else { - Console::error('Failed to delete cache file: '.$path); + Console::error('Failed to delete cache file: ' . $path); } } ); @@ -202,8 +200,7 @@ class DeletesV1 extends Worker } /** - * @param string $datetime - * + * @param string $datetime * @throws Exception */ protected function deleteCacheByDate(string $datetime): void @@ -212,7 +209,7 @@ class DeletesV1 extends Worker $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId) + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) ); $query = [ @@ -224,21 +221,22 @@ class DeletesV1 extends Worker $query, $dbForProject, function (Document $document) use ($cache, $projectId) { - $path = APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$projectId.DIRECTORY_SEPARATOR.$document->getId(); + $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); if ($cache->purge($document->getId())) { - Console::success('Deleting cache file: '.$path); + Console::success('Deleting cache file: ' . $path); } else { - Console::error('Failed to delete cache file: '.$path); + Console::error('Failed to delete cache file: ' . $path); } } ); }); } + /** - * @param Document $document database document - * @param Document $project + * @param Document $document database document + * @param Document $project */ protected function deleteDatabase(Document $document, Document $project): void { @@ -247,18 +245,18 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); - $this->deleteByGroup('database_'.$document->getInternalId(), [], $dbForProject, function ($document) use ($project) { + $this->deleteByGroup('database_' . $document->getInternalId(), [], $dbForProject, function ($document) use ($project) { $this->deleteCollection($document, $project); }); - $dbForProject->deleteCollection('database_'.$document->getInternalId()); + $dbForProject->deleteCollection('database_' . $document->getInternalId()); - $this->deleteAuditLogsByResource('database/'.$databaseId, $project); + $this->deleteAuditLogsByResource('database/' . $databaseId, $project); } /** - * @param Document $document teams document - * @param Document $project + * @param Document $document teams document + * @param Document $project */ protected function deleteCollection(Document $document, Document $project): void { @@ -275,33 +273,32 @@ class DeletesV1 extends Worker ); foreach ($relationships as $relationship) { - if (! $relationship['twoWay']) { + if (!$relationship['twoWay']) { continue; } - $relatedCollection = $dbForProject->getDocument('database_'.$databaseInternalId, $relationship['relatedCollection']); - $dbForProject->deleteDocument('attributes', $databaseInternalId.'_'.$relatedCollection->getInternalId().'_'.$relationship['twoWayKey']); - $dbForProject->deleteCachedDocument('database_'.$databaseInternalId, $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_'.$databaseInternalId.'_collection_'.$relatedCollection->getInternalId()); + $relatedCollection = $dbForProject->getDocument('database_' . $databaseInternalId, $relationship['relatedCollection']); + $dbForProject->deleteDocument('attributes', $databaseInternalId . '_' . $relatedCollection->getInternalId() . '_' . $relationship['twoWayKey']); + $dbForProject->deleteCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId()); + $dbForProject->deleteCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId()); } - $dbForProject->deleteCollection('database_'.$databaseInternalId.'_collection_'.$document->getInternalId()); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); $this->deleteByGroup('attributes', [ Query::equal('databaseInternalId', [$databaseInternalId]), - Query::equal('collectionInternalId', [$collectionInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) ], $dbForProject); $this->deleteByGroup('indexes', [ Query::equal('databaseInternalId', [$databaseInternalId]), - Query::equal('collectionInternalId', [$collectionInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) ], $dbForProject); - $this->deleteAuditLogsByResource('database/'.$databaseId.'/collection/'.$collectionId, $project); + $this->deleteAuditLogsByResource('database/' . $databaseId . '/collection/' . $collectionId, $project); } /** - * @param string $hourlyUsageRetentionDatetime - * + * @param string $hourlyUsageRetentionDatetime * @throws Exception */ protected function deleteUsageStats(string $hourlyUsageRetentionDatetime) @@ -317,8 +314,8 @@ class DeletesV1 extends Worker } /** - * @param Document $document teams document - * @param Document $project + * @param Document $document teams document + * @param Document $project */ protected function deleteMemberships(Document $document, Document $project): void { @@ -329,7 +326,7 @@ class DeletesV1 extends Worker $this->deleteByGroup( 'memberships', [ - Query::equal('teamInternalId', [$teamInternalId]), + Query::equal('teamInternalId', [$teamInternalId]) ], $dbForProject, function (Document $membership) use ($dbForProject) { @@ -340,9 +337,8 @@ class DeletesV1 extends Worker } /** - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return void - * * @throws \Exception */ protected function deleteProjectsByTeam(Document $document): void @@ -350,7 +346,7 @@ class DeletesV1 extends Worker $dbForConsole = $this->getConsoleDB(); $projects = $dbForConsole->find('projects', [ - Query::equal('teamInternalId', [$document->getInternalId()]), + Query::equal('teamInternalId', [$document->getInternalId()]) ]); foreach ($projects as $project) { @@ -360,8 +356,7 @@ class DeletesV1 extends Worker } /** - * @param Document $document project document - * + * @param Document $document project document * @throws Exception */ protected function deleteProject(Document $document): void @@ -373,7 +368,7 @@ class DeletesV1 extends Worker $dbForConsole = $this->getConsoleDB(); $domains = $dbForConsole->find('domains', [ - Query::equal('projectInternalId', [$projectInternalId]), + Query::equal('projectInternalId', [$projectInternalId]) ]); foreach ($domains as $domain) { @@ -397,22 +392,22 @@ class DeletesV1 extends Worker // Delete Platforms $this->deleteByGroup('platforms', [ - Query::equal('projectInternalId', [$projectInternalId]), + Query::equal('projectInternalId', [$projectInternalId]) ], $dbForConsole); // Delete Domains $this->deleteByGroup('domains', [ - Query::equal('projectInternalId', [$projectInternalId]), + Query::equal('projectInternalId', [$projectInternalId]) ], $dbForConsole); // Delete Keys $this->deleteByGroup('keys', [ - Query::equal('projectInternalId', [$projectInternalId]), + Query::equal('projectInternalId', [$projectInternalId]) ], $dbForConsole); // Delete Webhooks $this->deleteByGroup('webhooks', [ - Query::equal('projectInternalId', [$projectInternalId]), + Query::equal('projectInternalId', [$projectInternalId]) ], $dbForConsole); // Delete metadata tables @@ -436,8 +431,8 @@ class DeletesV1 extends Worker } /** - * @param Document $document user document - * @param Document $project + * @param Document $document user document + * @param Document $project */ protected function deleteUser(Document $document, Document $project): void { @@ -448,19 +443,19 @@ class DeletesV1 extends Worker // Delete all sessions of this user from the sessions table and update the sessions field of the user record $this->deleteByGroup('sessions', [ - Query::equal('userInternalId', [$userInternalId]), + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); $dbForProject->deleteCachedDocument('users', $userId); // Delete Memberships and decrement team membership counts $this->deleteByGroup('memberships', [ - Query::equal('userInternalId', [$userInternalId]), + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject, function (Document $document) use ($dbForProject) { if ($document->getAttribute('confirm')) { // Count only confirmed members $teamId = $document->getAttribute('teamId'); $team = $dbForProject->getDocument('teams', $teamId); - if (! $team->isEmpty()) { + if (!$team->isEmpty()) { $team = $dbForProject->updateDocument( 'teams', $teamId, @@ -473,18 +468,17 @@ class DeletesV1 extends Worker // Delete tokens $this->deleteByGroup('tokens', [ - Query::equal('userInternalId', [$userInternalId]), + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); // Delete identities $this->deleteByGroup('identities', [ - Query::equal('userInternalId', [$userInternalId]), + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); } /** - * @param string $datetime - * + * @param string $datetime * @throws Exception */ protected function deleteExecutionLogs(string $datetime): void @@ -493,7 +487,7 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); // Delete Executions $this->deleteByGroup('executions', [ - Query::lessThan('$createdAt', $datetime), + Query::lessThan('$createdAt', $datetime) ], $dbForProject); }); } @@ -511,14 +505,13 @@ class DeletesV1 extends Worker // Delete Sessions $this->deleteByGroup('sessions', [ - Query::lessThan('$createdAt', $expired), + Query::lessThan('$createdAt', $expired) ], $dbForProject); }); } /** - * @param string $datetime - * + * @param string $datetime * @throws Exception */ protected function deleteRealtimeUsage(string $datetime): void @@ -527,14 +520,13 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); // Delete Dead Realtime Logs $this->deleteByGroup('realtime', [ - Query::lessThan('timestamp', $datetime), + Query::lessThan('timestamp', $datetime) ], $dbForProject); }); } /** - * @param string $datetime - * + * @param string $datetime * @throws Exception */ protected function deleteAbuseLogs(string $datetime): void @@ -546,18 +538,17 @@ class DeletesV1 extends Worker $this->deleteForProjectIds(function (Document $project) use ($datetime) { $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); - $timeLimit = new TimeLimit('', 0, 1, $dbForProject); + $timeLimit = new TimeLimit("", 0, 1, $dbForProject); $abuse = new Abuse($timeLimit); $status = $abuse->cleanup($datetime); - if (! $status) { - throw new Exception('Failed to delete Abuse logs for project '.$projectId); + if (!$status) { + throw new Exception('Failed to delete Abuse logs for project ' . $projectId); } }); } /** - * @param string $datetime - * + * @param string $datetime * @throws Exception */ protected function deleteAuditLogs(string $datetime): void @@ -571,28 +562,28 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($project); $audit = new Audit($dbForProject); $status = $audit->cleanup($datetime); - if (! $status) { - throw new Exception('Failed to delete Audit logs for project'.$projectId); + if (!$status) { + throw new Exception('Failed to delete Audit logs for project' . $projectId); } }); } /** - * @param string $resource - * @param Document $project + * @param string $resource + * @param Document $project */ protected function deleteAuditLogsByResource(string $resource, Document $project): void { $dbForProject = $this->getProjectDB($project); $this->deleteByGroup(Audit::COLLECTION, [ - Query::equal('resource', [$resource]), + Query::equal('resource', [$resource]) ], $dbForProject); } /** - * @param Document $document function document - * @param Document $project + * @param Document $document function document + * @param Document $project */ protected function deleteFunction(Document $document, Document $project): void { @@ -604,41 +595,41 @@ class DeletesV1 extends Worker /** * Delete Variables */ - Console::info('Deleting variables for function '.$functionId); + Console::info("Deleting variables for function " . $functionId); $this->deleteByGroup('variables', [ - Query::equal('functionInternalId', [$functionInternalId]), + Query::equal('functionInternalId', [$functionInternalId]) ], $dbForProject); /** * Delete Deployments */ - Console::info('Deleting deployments for function '.$functionId); + Console::info("Deleting deployments for function " . $functionId); $storageFunctions = $this->getFunctionsDevice($projectId); $deploymentIds = []; $this->deleteByGroup('deployments', [ - Query::equal('resourceId', [$functionId]), + Query::equal('resourceId', [$functionId]) ], $dbForProject, function (Document $document) use ($storageFunctions, &$deploymentIds) { $deploymentIds[] = $document->getId(); if ($storageFunctions->delete($document->getAttribute('path', ''), true)) { - Console::success('Deleted deployment files: '.$document->getAttribute('path', '')); + Console::success('Deleted deployment files: ' . $document->getAttribute('path', '')); } else { - Console::error('Failed to delete deployment files: '.$document->getAttribute('path', '')); + Console::error('Failed to delete deployment files: ' . $document->getAttribute('path', '')); } }); /** * Delete builds */ - Console::info('Deleting builds for function '.$functionId); + Console::info("Deleting builds for function " . $functionId); $storageBuilds = $this->getBuildsDevice($projectId); foreach ($deploymentIds as $deploymentId) { $this->deleteByGroup('builds', [ - Query::equal('deploymentId', [$deploymentId]), - ], $dbForProject, function (Document $document) use ($storageBuilds) { + Query::equal('deploymentId', [$deploymentId]) + ], $dbForProject, function (Document $document) use ($storageBuilds, $deploymentId) { if ($storageBuilds->delete($document->getAttribute('outputPath', ''), true)) { - Console::success('Deleted build files: '.$document->getAttribute('outputPath', '')); + Console::success('Deleted build files: ' . $document->getAttribute('outputPath', '')); } else { - Console::error('Failed to delete build files: '.$document->getAttribute('outputPath', '')); + Console::error('Failed to delete build files: ' . $document->getAttribute('outputPath', '')); } }); } @@ -646,17 +637,17 @@ class DeletesV1 extends Worker /** * Delete Executions */ - Console::info('Deleting executions for function '.$functionId); + Console::info("Deleting executions for function " . $functionId); $this->deleteByGroup('executions', [ - Query::equal('functionId', [$functionId]), + Query::equal('functionId', [$functionId]) ], $dbForProject); // TODO: Request executor to delete runtime } /** - * @param Document $document deployment document - * @param Document $project + * @param Document $document deployment document + * @param Document $project */ protected function deleteDeployment(Document $document, Document $project): void { @@ -668,44 +659,45 @@ class DeletesV1 extends Worker /** * Delete deployment files */ - Console::info('Deleting deployment files for deployment '.$deploymentId); + Console::info("Deleting deployment files for deployment " . $deploymentId); $storageFunctions = $this->getFunctionsDevice($projectId); if ($storageFunctions->delete($document->getAttribute('path', ''), true)) { - Console::success('Deleted deployment files: '.$document->getAttribute('path', '')); + Console::success('Deleted deployment files: ' . $document->getAttribute('path', '')); } else { - Console::error('Failed to delete deployment files: '.$document->getAttribute('path', '')); + Console::error('Failed to delete deployment files: ' . $document->getAttribute('path', '')); } /** * Delete builds */ - Console::info('Deleting builds for deployment '.$deploymentId); + Console::info("Deleting builds for deployment " . $deploymentId); $storageBuilds = $this->getBuildsDevice($projectId); $this->deleteByGroup('builds', [ - Query::equal('deploymentId', [$deploymentId]), + Query::equal('deploymentId', [$deploymentId]) ], $dbForProject, function (Document $document) use ($storageBuilds) { if ($storageBuilds->delete($document->getAttribute('outputPath', ''), true)) { - Console::success('Deleted build files: '.$document->getAttribute('outputPath', '')); + Console::success('Deleted build files: ' . $document->getAttribute('outputPath', '')); } else { - Console::error('Failed to delete build files: '.$document->getAttribute('outputPath', '')); + Console::error('Failed to delete build files: ' . $document->getAttribute('outputPath', '')); } }); // TODO: Request executor to delete runtime } + /** - * @param Document $document to be deleted - * @param Database $database to delete it from - * @param callable|null $callback to perform after document is deleted - * @return bool + * @param Document $document to be deleted + * @param Database $database to delete it from + * @param callable|null $callback to perform after document is deleted * + * @return bool * @throws \Utopia\Database\Exception\Authorization */ protected function deleteById(Document $document, Database $database, callable $callback = null): bool { if ($database->deleteDocument($document->getCollection(), $document->getId())) { - Console::success('Deleted document "'.$document->getId().'" successfully'); + Console::success('Deleted document "' . $document->getId() . '" successfully'); if (is_callable($callback)) { $callback($document); @@ -713,15 +705,13 @@ class DeletesV1 extends Worker return true; } else { - Console::error('Failed to delete document: '.$document->getId()); - + Console::error('Failed to delete document: ' . $document->getId()); return false; } } /** - * @param callable $callback - * + * @param callable $callback * @throws Exception */ protected function deleteForProjectIds(callable $callback): void @@ -743,7 +733,7 @@ class DeletesV1 extends Worker /** @var string[] $projectIds */ $sum = count($projects); - Console::info('Executing delete function for chunk #'.$chunk.'. Found '.$sum.' projects'); + Console::info('Executing delete function for chunk #' . $chunk . '. Found ' . $sum . ' projects'); foreach ($projects as $project) { $callback($project); $count++; @@ -751,15 +741,14 @@ class DeletesV1 extends Worker } $executionEnd = \microtime(true); - Console::info("Found {$count} projects ".($executionEnd - $executionStart).' seconds'); + Console::info("Found {$count} projects " . ($executionEnd - $executionStart) . " seconds"); } /** - * @param string $collection collectionID - * @param array $queries - * @param Database $database - * @param callable|null $callback - * + * @param string $collection collectionID + * @param array $queries + * @param Database $database + * @param callable|null $callback * @throws Exception */ protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void @@ -780,7 +769,7 @@ class DeletesV1 extends Worker $sum = count($results); - Console::info('Deleting chunk #'.$chunk.'. Found '.$sum.' documents in collection '.$database->getNamespace().'_'.$collection); + Console::info('Deleting chunk #' . $chunk . '. Found ' . $sum . ' documents in collection ' . $database->getNamespace() . '_' . $collection); foreach ($results as $document) { $this->deleteById($document, $database, $callback); @@ -793,14 +782,14 @@ class DeletesV1 extends Worker $executionEnd = \microtime(true); - Console::info("Deleted {$count} document by group in ".($executionEnd - $executionStart).' seconds'); + Console::info("Deleted {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); } /** - * @param string $collection collectionID - * @param Query[] $queries - * @param Database $database - * @param callable $callback + * @param string $collection collectionID + * @param Query[] $queries + * @param Database $database + * @param callable $callback */ protected function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void { @@ -840,12 +829,11 @@ class DeletesV1 extends Worker $executionEnd = \microtime(true); - Console::info("Listed {$count} document by group in ".($executionEnd - $executionStart).' seconds'); + Console::info("Listed {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); } /** - * @param Document $document certificates document - * + * @param Document $document certificates document * @throws \Utopia\Database\Exception\Authorization */ protected function deleteCertificates(Document $document): void @@ -855,10 +843,10 @@ class DeletesV1 extends Worker // If domain has certificate generated if (isset($document['certificateId'])) { $domainUsingCertificate = $consoleDB->findOne('domains', [ - Query::equal('certificateId', [$document['certificateId']]), + Query::equal('certificateId', [$document['certificateId']]) ]); - if (! $domainUsingCertificate) { + if (!$domainUsingCertificate) { $mainDomain = App::getEnv('_APP_DOMAIN_TARGET', ''); if ($mainDomain === $document->getAttribute('domain')) { $domainUsingCertificate = $mainDomain; @@ -868,14 +856,13 @@ class DeletesV1 extends Worker // If certificate is still used by some domain, mark we can't delete. // Current domain should not be found, because we only have copy. Original domain is already deleted from database. if ($domainUsingCertificate) { - Console::warning('Skipping certificate deletion, because a domain is still using it.'); - + Console::warning("Skipping certificate deletion, because a domain is still using it."); return; } } $domain = $document->getAttribute('domain'); - $directory = APP_STORAGE_CERTIFICATES.'/'.$domain; + $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; $checkTraversal = realpath($directory) === $directory; if ($domain && $checkTraversal && is_dir($directory)) { @@ -885,7 +872,7 @@ class DeletesV1 extends Worker } // Delete files, so Traefik is aware of change - array_map('unlink', glob($directory.'/*.*')); + array_map('unlink', glob($directory . '/*.*')); rmdir($directory); Console::info("Deleted certificate files for {$domain}"); } else { @@ -897,7 +884,7 @@ class DeletesV1 extends Worker { $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); - $dbForProject->deleteCollection('bucket_'.$document->getInternalId()); + $dbForProject->deleteCollection('bucket_' . $document->getInternalId()); $device = $this->getFilesDevice($projectId); diff --git a/app/workers/functions.php b/app/workers/functions.php index d5aab70534..7dec0ce90c 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -1,10 +1,11 @@ getAttribute('runtime'), $runtimes)) { - throw new Exception('Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); + if (!\array_key_exists($function->getAttribute('runtime'), $runtimes)) { + throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } $runtime = $runtimes[$function->getAttribute('runtime')]; @@ -109,6 +109,7 @@ Server::setResource('execute', function () { /** * Usage */ + $queueForUsage ->addMetric(METRIC_EXECUTIONS, 1) // per project ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1); // per function @@ -119,7 +120,6 @@ Server::setResource('execute', function () { $vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) { $carry[$var->getAttribute('key')] = $var->getAttribute('value'); - return $carry; }, []); @@ -164,7 +164,7 @@ Server::setResource('execute', function () { } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); $execution - ->setAttribute('duration', (float) $interval->format('%s.%f')) + ->setAttribute('duration', (float)$interval->format('%s.%f')) ->setAttribute('status', 'failed') ->setAttribute('statusCode', $th->getCode()) ->setAttribute('stderr', $th->getMessage()); @@ -195,7 +195,7 @@ Server::setResource('execute', function () { /** Trigger realtime event */ $allEvents = Event::generateEvents('functions.[functionId].executions.[executionId].update', [ 'functionId' => $function->getId(), - 'executionId' => $execution->getId(), + 'executionId' => $execution->getId() ]); $target = Realtime::fromPayload( // Pass first, most verbose event pattern @@ -220,9 +220,10 @@ Server::setResource('execute', function () { /** Trigger usage queue */ $queueForUsage ->setProject($project) - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int) ($execution->getAttribute('duration') * 1000))// per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int) ($execution->getAttribute('duration') * 1000)) - ->trigger(); + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) + ->trigger() + ; }; }); @@ -252,7 +253,7 @@ $server->job() return; } - if (! empty($events)) { + if (!empty($events)) { $limit = 30; $sum = 30; $offset = 0; @@ -261,19 +262,19 @@ $server->job() while ($sum >= $limit) { $functions = $dbForProject->find('functions', [ Query::limit($limit), - Query::offset($offset), + Query::offset($offset) ]); $sum = \count($functions); $offset = $offset + $limit; - Console::log('Fetched '.$sum.' functions...'); + Console::log('Fetched ' . $sum . ' functions...'); foreach ($functions as $function) { - if (! array_intersect($events, $function->getAttribute('events', []))) { + if (!array_intersect($events, $function->getAttribute('events', []))) { continue; } - Console::success('Iterating function: '.$function->getAttribute('name')); + Console::success('Iterating function: ' . $function->getAttribute('name')); try { $execute( log: $log, @@ -290,13 +291,12 @@ $server->job() executionId: null, jwt: null ); - Console::success('Triggered function: '.$events[0]); + Console::success('Triggered function: ' . $events[0]); } catch (\Throwable $th) { - Console::error('Failed to execute '.$function->getId().' with error: '.$th->getMessage()); + Console::error("Failed to execute " . $function->getId() . " with error: " . $th->getMessage()); } } } - return; } diff --git a/app/workers/mails.php b/app/workers/mails.php index d8949c0222..e1ce8307ac 100644 --- a/app/workers/mails.php +++ b/app/workers/mails.php @@ -1,20 +1,20 @@ args['recipient']; $subject = $this->args['subject']; $name = $this->args['name']; @@ -49,7 +49,7 @@ class MailsV1 extends Worker $mail->clearBCCs(); $mail->clearCCs(); - $mail->setFrom(App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), (empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')) : $from)); + $mail->setFrom(App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), (empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')) : $from)); $mail->addAddress($recipient, $name); if (isset($smtp['replyTo'])) { $mail->addReplyTo($smtp['replyTo']); @@ -61,7 +61,7 @@ class MailsV1 extends Worker try { $mail->send(); } catch (\Exception $error) { - throw new Exception('Error sending mail: '.$error->getMessage(), 500); + throw new Exception('Error sending mail: ' . $error->getMessage(), 500); } } @@ -77,14 +77,14 @@ class MailsV1 extends Worker $mail->XMailer = 'Appwrite Mailer'; $mail->Host = $smtp['host']; $mail->Port = $smtp['port']; - $mail->SMTPAuth = (! empty($username) && ! empty($password)); + $mail->SMTPAuth = (!empty($username) && !empty($password)); $mail->Username = $username; $mail->Password = $password; $mail->SMTPSecure = $smtp['secure'] === 'tls'; $mail->SMTPAutoTLS = false; $mail->CharSet = 'UTF-8'; - $from = \urldecode($smtp['senderName'] ?? App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')); + $from = \urldecode($smtp['senderName'] ?? App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); $email = $smtp['senderEmail'] ?? App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $mail->setFrom($email, $from); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index b826dc1c3f..84af6fa802 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -2,43 +2,41 @@ use Appwrite\Resque\Worker; use Utopia\CLI\Console; -use Utopia\Messaging\Adapters\Email as EmailAdapter; -use Utopia\Messaging\Adapters\Email\Mailgun; -use Utopia\Messaging\Adapters\Email\SendGrid; -use Utopia\Messaging\Adapters\Push\APNS; -use Utopia\Messaging\Adapters\Push as PushAdapter; -use Utopia\Messaging\Adapters\Push\FCM; use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Adapters\SMS\Msg91; use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; use Utopia\Messaging\Adapters\SMS\Twilio; use Utopia\Messaging\Adapters\SMS\Vonage; +use Utopia\Messaging\Adapters\Push as PushAdapter; +use Utopia\Messaging\Adapters\Push\APNS; +use Utopia\Messaging\Adapters\Push\FCM; +use Utopia\Messaging\Adapters\Email as EmailAdapter; +use Utopia\Messaging\Adapters\Email\Mailgun; +use Utopia\Messaging\Adapters\Email\SendGrid; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Messaging V1 Worker'); -Console::success(APP_NAME.' messaging worker v1 has started'."\n"); +Console::success(APP_NAME . ' messaging worker v1 has started' . "\n"); class MessagingV1 extends Worker { protected ?SMSAdapter $sms = null; - protected ?PushAdapter $push = null; - protected ?EmailAdapter $email = null; + protected ?string $from = null; public function getName(): string { - return 'mails'; + return "mails"; } public function sms($record): ?SMSAdapter { $credentials = $record->getAttribute('credentials'); - return match ($record->getAttribute('provider')) { 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), @@ -52,7 +50,6 @@ class MessagingV1 extends Worker public function push($record): ?PushAdapter { $credentials = $record->getAttribute('credentials'); - return match ($record->getAttribute('provider')) { 'apns' => new APNS( $credentials['authKey'], @@ -69,7 +66,6 @@ class MessagingV1 extends Worker public function email($record): ?EmailAdapter { $credentials = $record->getAttribute('credentials'); - return match ($record->getAttribute('provider')) { 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain']), 'sendgrid' => new SendGrid($credentials['apiKey']), @@ -96,9 +92,9 @@ class MessagingV1 extends Worker default => null }; - // Query for the provider - // switch on provider name - // call function passing needed credentials returns required provider. + // Query for the provider + // switch on provider name + // call function passing needed credentials returns required provider. $messageId = $this->args['messageId']; $messageRecord = @@ -113,6 +109,7 @@ class MessagingV1 extends Worker default => null }; + $provider->send($message); } @@ -144,7 +141,7 @@ class MessagingV1 extends Worker return [ 'from' => $from, 'to' => $to, - 'body' => $body, + 'body' => $body ]; } @@ -159,7 +156,7 @@ class MessagingV1 extends Worker 'to' => $to, 'title' => $title, 'body' => $body, - 'data' => $data, + 'data' => $data ]; } } diff --git a/app/workers/migrations.php b/app/workers/migrations.php index 99529d4fb2..0f8194acf8 100644 --- a/app/workers/migrations.php +++ b/app/workers/migrations.php @@ -18,10 +18,10 @@ use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; use Utopia\Migration\Transfer; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Migrations V1 Worker'); -Console::success(APP_NAME.' Migrations worker v1 has started'); +Console::success(APP_NAME . ' Migrations worker v1 has started'); class MigrationsV1 extends Worker { diff --git a/app/workers/usage.php b/app/workers/usage.php index 3e76d8e8e7..0c9dcbc5aa 100644 --- a/app/workers/usage.php +++ b/app/workers/usage.php @@ -1,17 +1,17 @@ setNamespace('_'.$projectInternalId); + $dbForProject->setNamespace('_' . $projectInternalId); switch (true) { case $document->getCollection() === 'users': // users $sessions = count($document->getAttribute(METRIC_SESSIONS, 0)); - if (! empty($sessions)) { + if (!empty($sessions)) { $metrics[] = [ 'key' => METRIC_SESSIONS, 'value' => ($sessions * -1), @@ -55,28 +55,28 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); - if (! empty($collections['value'])) { + $collections = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); + if (!empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, 'value' => ($collections['value'] * -1), ]; } - if (! empty($documents['value'])) { + if (!empty($documents['value'])) { $metrics[] = [ 'key' => METRIC_DOCUMENTS, 'value' => ($documents['value'] * -1), ]; } break; - case str_starts_with($document->getCollection(), 'database_') && ! str_contains($document->getCollection(), 'collection'): //collections + case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; - $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); + $documents = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); - if (! empty($documents['value'])) { + if (!empty($documents['value'])) { $metrics[] = [ 'key' => METRIC_DOCUMENTS, 'value' => ($documents['value'] * -1), @@ -89,17 +89,17 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); - if (! empty($files['value'])) { + if (!empty($files['value'])) { $metrics[] = [ 'key' => METRIC_FILES, 'value' => ($files['value'] * -1), ]; } - if (! empty($storage['value'])) { + if (!empty($storage['value'])) { $metrics[] = [ 'key' => METRIC_FILES_STORAGE, 'value' => ($storage['value'] * -1), @@ -108,57 +108,57 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools break; case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD.str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); - if (! empty($deployments['value'])) { + if (!empty($deployments['value'])) { $metrics[] = [ 'key' => METRIC_DEPLOYMENTS, 'value' => ($deployments['value'] * -1), ]; } - if (! empty($deploymentsStorage['value'])) { + if (!empty($deploymentsStorage['value'])) { $metrics[] = [ 'key' => METRIC_DEPLOYMENTS_STORAGE, 'value' => ($deploymentsStorage['value'] * -1), ]; } - if (! empty($builds['value'])) { + if (!empty($builds['value'])) { $metrics[] = [ 'key' => METRIC_BUILDS, 'value' => ($builds['value'] * -1), ]; } - if (! empty($buildsStorage['value'])) { + if (!empty($buildsStorage['value'])) { $metrics[] = [ 'key' => METRIC_BUILDS_STORAGE, 'value' => ($buildsStorage['value'] * -1), ]; } - if (! empty($buildsCompute['value'])) { + if (!empty($buildsCompute['value'])) { $metrics[] = [ 'key' => METRIC_BUILDS_COMPUTE, 'value' => ($buildsCompute['value'] * -1), ]; } - if (! empty($executions['value'])) { + if (!empty($executions['value'])) { $metrics[] = [ 'key' => METRIC_EXECUTIONS, 'value' => ($executions['value'] * -1), ]; } - if (! empty($executionsCompute['value'])) { + if (!empty($executionsCompute['value'])) { $metrics[] = [ 'key' => METRIC_EXECUTIONS_COMPUTE, 'value' => ($executionsCompute['value'] * -1), @@ -169,18 +169,20 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools break; } } catch (\Exception $e) { - console::error('[reducer] '.' {DateTime::now()} '." {$projectInternalId} "." {$e->getMessage()}"); + console::error("[reducer] " . " {DateTime::now()} " . " {$projectInternalId} " . " {$e->getMessage()}"); } finally { $pools->reclaim(); } }; }, ['cache', 'register', 'pools']); + $server->job() ->inject('message') ->inject('reduce') ->action(function (Message $message, callable $reduce) use (&$stats) { + $payload = $message->getPayload() ?? []; $project = new Document($payload['project'] ?? []); $projectId = $project->getInternalId(); @@ -189,19 +191,18 @@ $server->job() continue; } - $reduce( - database: $project->getAttribute('database'), - projectInternalId: $project->getInternalId(), - document: new Document($document), - metrics: $payload['metrics'], - ); + $reduce( + database: $project->getAttribute('database'), + projectInternalId: $project->getInternalId(), + document: new Document($document), + metrics: $payload['metrics'], + ); } $stats[$projectId]['database'] = $project->getAttribute('database'); foreach ($payload['metrics'] ?? [] as $metric) { - if (! isset($stats[$projectId]['keys'][$metric['key']])) { + if (!isset($stats[$projectId]['keys'][$metric['key']])) { $stats[$projectId]['keys'][$metric['key']] = $metric['value']; - continue; } $stats[$projectId]['keys'][$metric['key']] += $metric['value']; @@ -214,7 +215,8 @@ $server ->inject('cache') ->inject('pools') ->action(function ($register, $cache, $pools) use ($periods, &$stats) { - Timer::tick(30000, function () use ($cache, $pools, $periods, &$stats) { + Timer::tick(30000, function () use ($register, $cache, $pools, $periods, &$stats) { + $offset = count($stats); $projects = array_slice($stats, 0, $offset, true); array_splice($stats, 0, $offset); @@ -229,7 +231,7 @@ $server $cache ); - $dbForProject->setNamespace('_'.$projectInternalId); + $dbForProject->setNamespace('_' . $projectInternalId); foreach ($project['keys'] ?? [] as $key => $value) { if ($value == 0) { @@ -268,7 +270,7 @@ $server } } } - if (! empty($project['keys'])) { + if (!empty($project['keys'])) { $dbForProject->createDocument('statsLogger', new Document([ 'time' => DateTime::now(), 'metrics' => $project['keys'], @@ -276,7 +278,7 @@ $server } } catch (\Exception $e) { $now = DateTime::now(); - console::error('[Error] '." Time: {$now} "." projectInternalId: {$projectInternalId}"." File: {$e->getFile()}"." Line: {$e->getLine()} "." message: {$e->getMessage()}"); + console::error("[Error] " . " Time: {$now} " . " projectInternalId: {$projectInternalId}" . " File: {$e->getFile()}" . " Line: {$e->getLine()} " . " message: {$e->getMessage()}"); } finally { $pools->reclaim(); } diff --git a/app/workers/webhooks.php b/app/workers/webhooks.php index 33fd4e5f6c..4048581c0c 100644 --- a/app/workers/webhooks.php +++ b/app/workers/webhooks.php @@ -5,10 +5,10 @@ use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Document; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Webhooks V1 Worker'); -Console::success(APP_NAME.' webhooks worker v1 has started'); +Console::success(APP_NAME . ' webhooks worker v1 has started'); class WebhooksV1 extends Worker { @@ -16,7 +16,7 @@ class WebhooksV1 extends Worker public function getName(): string { - return 'webhooks'; + return "webhooks"; } public function init(): void @@ -36,7 +36,7 @@ class WebhooksV1 extends Worker } } - if (! empty($this->errors)) { + if (!empty($this->errors)) { throw new Exception(\implode(" / \n\n", $this->errors)); } } @@ -45,7 +45,7 @@ class WebhooksV1 extends Worker { $url = \rawurldecode($webhook->getAttribute('url')); $signatureKey = $webhook->getAttribute('signatureKey'); - $signature = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $signature = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $httpUser = $webhook->getAttribute('httpUser'); $httpPass = $webhook->getAttribute('httpPass'); $ch = \curl_init($webhook->getAttribute('url')); @@ -64,28 +64,28 @@ class WebhooksV1 extends Worker CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', - 'Content-Length: '.\strlen($payload), - 'X-'.APP_NAME.'-Webhook-Id: '.$webhook->getId(), - 'X-'.APP_NAME.'-Webhook-Events: '.implode(',', $events), - 'X-'.APP_NAME.'-Webhook-Name: '.$webhook->getAttribute('name', ''), - 'X-'.APP_NAME.'-Webhook-User-Id: '.$user->getId(), - 'X-'.APP_NAME.'-Webhook-Project-Id: '.$project->getId(), - 'X-'.APP_NAME.'-Webhook-Signature: '.$signature, + 'Content-Length: ' . \strlen($payload), + 'X-' . APP_NAME . '-Webhook-Id: ' . $webhook->getId(), + 'X-' . APP_NAME . '-Webhook-Events: ' . implode(',', $events), + 'X-' . APP_NAME . '-Webhook-Name: ' . $webhook->getAttribute('name', ''), + 'X-' . APP_NAME . '-Webhook-User-Id: ' . $user->getId(), + 'X-' . APP_NAME . '-Webhook-Project-Id: ' . $project->getId(), + 'X-' . APP_NAME . '-Webhook-Signature: ' . $signature, ] ); - if (! $webhook->getAttribute('security', true)) { + if (!$webhook->getAttribute('security', true)) { \curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); \curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - if (! empty($httpUser) && ! empty($httpPass)) { + if (!empty($httpUser) && !empty($httpPass)) { \curl_setopt($ch, CURLOPT_USERPWD, "$httpUser:$httpPass"); \curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); } if (false === \curl_exec($ch)) { - $this->errors[] = \curl_error($ch).' in events '.implode(', ', $events).' for webhook '.$webhook->getAttribute('name'); + $this->errors[] = \curl_error($ch) . ' in events ' . implode(', ', $events) . ' for webhook ' . $webhook->getAttribute('name'); } \curl_close($ch); diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 98a0cf27d8..e97c271ae2 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -9,8 +9,8 @@ use Appwrite\Auth\Hash\Phpass; use Appwrite\Auth\Hash\Scrypt; use Appwrite\Auth\Hash\Scryptmodified; use Appwrite\Auth\Hash\Sha; -use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; @@ -25,69 +25,49 @@ class Auth 'phpass', 'scrypt', 'scryptMod', - 'plaintext', + 'plaintext' ]; public const DEFAULT_ALGO = 'argon2'; - public const DEFAULT_ALGO_OPTIONS = ['type' => 'argon2', 'memoryCost' => 2048, 'timeCost' => 4, 'threads' => 3]; /** * User Roles. */ public const USER_ROLE_ANY = 'any'; - public const USER_ROLE_GUESTS = 'guests'; - public const USER_ROLE_USERS = 'users'; - public const USER_ROLE_ADMIN = 'admin'; - public const USER_ROLE_DEVELOPER = 'developer'; - public const USER_ROLE_OWNER = 'owner'; - public const USER_ROLE_APPS = 'apps'; - public const USER_ROLE_SYSTEM = 'system'; /** * Token Types. */ public const TOKEN_TYPE_LOGIN = 1; // Deprecated - public const TOKEN_TYPE_VERIFICATION = 2; - public const TOKEN_TYPE_RECOVERY = 3; - public const TOKEN_TYPE_INVITE = 4; - public const TOKEN_TYPE_MAGIC_URL = 5; - public const TOKEN_TYPE_PHONE = 6; /** * Session Providers. */ public const SESSION_PROVIDER_EMAIL = 'email'; - public const SESSION_PROVIDER_ANONYMOUS = 'anonymous'; - public const SESSION_PROVIDER_MAGIC_URL = 'magic-url'; - public const SESSION_PROVIDER_PHONE = 'phone'; /** * Token Expiration times. */ public const TOKEN_EXPIRATION_LOGIN_LONG = 31536000; /* 1 year */ - public const TOKEN_EXPIRATION_LOGIN_SHORT = 3600; /* 1 hour */ - public const TOKEN_EXPIRATION_RECOVERY = 3600; /* 1 hour */ - public const TOKEN_EXPIRATION_CONFIRM = 3600 * 24 * 7; /* 7 days */ - public const TOKEN_EXPIRATION_PHONE = 60 * 15; /* 15 minutes */ /** @@ -113,6 +93,7 @@ class Auth * Set Cookie Name. * * @param $string + * * @return string */ public static function setCookieName($string) @@ -123,8 +104,9 @@ class Auth /** * Encode Session. * - * @param string $id - * @param string $secret + * @param string $id + * @param string $secret + * * @return string */ public static function encodeSession($id, $secret) @@ -138,7 +120,8 @@ class Auth /** * Decode Session. * - * @param string $session + * @param string $session + * * @return array * * @throws \Exception @@ -148,7 +131,7 @@ class Auth $session = \json_decode(\base64_decode($session), true); $default = ['id' => null, 'secret' => '']; - if (! \is_array($session)) { + if (!\is_array($session)) { return $default; } @@ -161,6 +144,7 @@ class Auth * One-way encryption * * @param $string + * * @return string */ public static function hash(string $string) @@ -173,9 +157,10 @@ class Auth * * One way string hashing for user passwords * - * @param string $string - * @param string $algo hashing algorithm to use - * @param array $options algo-specific options + * @param string $string + * @param string $algo hashing algorithm to use + * @param array $options algo-specific options + * * @return bool|string|null */ public static function passwordHash(string $string, string $algo, array $options = []) @@ -186,51 +171,45 @@ class Auth $options = Auth::DEFAULT_ALGO_OPTIONS; } - if (! \in_array($algo, Auth::SUPPORTED_ALGOS)) { - throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); + if (!\in_array($algo, Auth::SUPPORTED_ALGOS)) { + throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); } switch ($algo) { case 'argon2': $hasher = new Argon2($options); - return $hasher->hash($string); case 'bcrypt': $hasher = new Bcrypt($options); - return $hasher->hash($string); case 'md5': $hasher = new Md5($options); - return $hasher->hash($string); case 'sha': $hasher = new Sha($options); - return $hasher->hash($string); case 'phpass': $hasher = new Phpass($options); - return $hasher->hash($string); case 'scrypt': $hasher = new Scrypt($options); - return $hasher->hash($string); case 'scryptMod': $hasher = new Scryptmodified($options); - return $hasher->hash($string); default: - throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); + throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); } } /** * Password verify. * - * @param string $plain - * @param string $hash - * @param string $algo hashing algorithm used to hash - * @param array $options algo-specific options + * @param string $plain + * @param string $hash + * @param string $algo hashing algorithm used to hash + * @param array $options algo-specific options + * * @return bool */ public static function passwordVerify(string $plain, string $hash, string $algo, array $options = []) @@ -241,41 +220,34 @@ class Auth $options = Auth::DEFAULT_ALGO_OPTIONS; } - if (! \in_array($algo, Auth::SUPPORTED_ALGOS)) { - throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); + if (!\in_array($algo, Auth::SUPPORTED_ALGOS)) { + throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); } switch ($algo) { case 'argon2': $hasher = new Argon2($options); - return $hasher->verify($plain, $hash); case 'bcrypt': $hasher = new Bcrypt($options); - return $hasher->verify($plain, $hash); case 'md5': $hasher = new Md5($options); - return $hasher->verify($plain, $hash); case 'sha': $hasher = new Sha($options); - return $hasher->verify($plain, $hash); case 'phpass': $hasher = new Phpass($options); - return $hasher->verify($plain, $hash); case 'scrypt': $hasher = new Scrypt($options); - return $hasher->verify($plain, $hash); case 'scryptMod': $hasher = new Scryptmodified($options); - return $hasher->verify($plain, $hash); default: - throw new \Exception('Hashing algorithm \''.$algo.'\' is not supported.'); + throw new \Exception('Hashing algorithm \'' . $algo . '\' is not supported.'); } } @@ -284,7 +256,8 @@ class Auth * * Generate random password string * - * @param int $length + * @param int $length + * * @return string */ public static function passwordGenerator(int $length = 20): string @@ -297,7 +270,8 @@ class Auth * * Generate random password string * - * @param int $length + * @param int $length + * * @return string */ public static function tokenGenerator(int $length = 128): string @@ -310,7 +284,8 @@ class Auth * * Generate random code string * - * @param int $length + * @param int $length + * * @return string */ public static function codeGenerator(int $length = 6): string @@ -327,9 +302,10 @@ class Auth /** * Verify token and check that its not expired. * - * @param array $tokens - * @param int $type - * @param string $secret + * @param array $tokens + * @param int $type + * @param string $secret + * * @return bool|string */ public static function tokenVerify(array $tokens, int $type, string $secret) @@ -344,7 +320,7 @@ class Auth $token->getAttribute('secret') === self::hash($secret) && DateTime::formatTz($token->getAttribute('expire')) >= DateTime::formatTz(DateTime::now()) ) { - return (string) $token->getId(); + return (string)$token->getId(); } } @@ -373,9 +349,10 @@ class Auth /** * Verify session and check that its not expired. * - * @param array $sessions - * @param string $secret - * @param string $expires + * @param array $sessions + * @param string $secret + * @param string $expires + * * @return bool|string */ public static function sessionVerify(array $sessions, string $secret, int $expires) @@ -398,7 +375,8 @@ class Auth /** * Is Privileged User? * - * @param array $roles + * @param array $roles + * * @return bool */ public static function isPrivilegedUser(array $roles): bool @@ -417,7 +395,8 @@ class Auth /** * Is App User? * - * @param array $roles + * @param array $roles + * * @return bool */ public static function isAppUser(array $roles): bool @@ -432,14 +411,14 @@ class Auth /** * Returns all roles for a user. * - * @param Document $user + * @param Document $user * @return array */ public static function getRoles(Document $user): array { $roles = []; - if (! self::isPrivilegedUser(Authorization::getRoles()) && ! self::isAppUser(Authorization::getRoles())) { + if (!self::isPrivilegedUser(Authorization::getRoles()) && !self::isAppUser(Authorization::getRoles())) { if ($user->getId()) { $roles[] = Role::user($user->getId())->toString(); $roles[] = Role::users()->toString(); @@ -460,7 +439,7 @@ class Auth } foreach ($user->getAttribute('memberships', []) as $node) { - if (! isset($node['confirm']) || ! $node['confirm']) { + if (!isset($node['confirm']) || !$node['confirm']) { continue; } @@ -477,7 +456,7 @@ class Auth } foreach ($user->getAttribute('labels', []) as $label) { - $roles[] = 'label:'.$label; + $roles[] = 'label:' . $label; } return $roles; diff --git a/src/Appwrite/Auth/Hash.php b/src/Appwrite/Auth/Hash.php index caf4771fcd..7134057581 100644 --- a/src/Appwrite/Auth/Hash.php +++ b/src/Appwrite/Auth/Hash.php @@ -5,13 +5,13 @@ namespace Appwrite\Auth; abstract class Hash { /** - * @var array Hashing-algo specific options - */ + * @var array $options Hashing-algo specific options + */ protected array $options = []; /** - * @param array $options Hashing-algo specific options - */ + * @param array $options Hashing-algo specific options + */ public function __construct(array $options = []) { $this->setOptions($options); @@ -20,12 +20,11 @@ abstract class Hash /** * Set hashing algo options * - * @param array $options Hashing-algo specific options - */ + * @param array $options Hashing-algo specific options + */ public function setOptions(array $options): self { $this->options = \array_merge([], $this->getDefaultOptions(), $options); - return $this; } @@ -33,22 +32,24 @@ abstract class Hash * Get hashing algo options * * @return array $options Hashing-algo specific options - */ + */ public function getOptions(): array { return $this->options; } /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ abstract public function hash(string $password): string; /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ abstract public function verify(string $password, string $hash): bool; diff --git a/src/Appwrite/Auth/Hash/Argon2.php b/src/Appwrite/Auth/Hash/Argon2.php index 0e9c2fcf36..c723b077b1 100644 --- a/src/Appwrite/Auth/Hash/Argon2.php +++ b/src/Appwrite/Auth/Hash/Argon2.php @@ -15,7 +15,8 @@ use Appwrite\Auth\Hash; class Argon2 extends Hash { /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -24,9 +25,10 @@ class Argon2 extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { diff --git a/src/Appwrite/Auth/Hash/Bcrypt.php b/src/Appwrite/Auth/Hash/Bcrypt.php index c54cf3d452..8b6177f33a 100644 --- a/src/Appwrite/Auth/Hash/Bcrypt.php +++ b/src/Appwrite/Auth/Hash/Bcrypt.php @@ -14,7 +14,8 @@ use Appwrite\Auth\Hash; class Bcrypt extends Hash { /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -23,9 +24,10 @@ class Bcrypt extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -39,6 +41,6 @@ class Bcrypt extends Hash */ public function getDefaultOptions(): array { - return ['cost' => 8]; + return [ 'cost' => 8 ]; } } diff --git a/src/Appwrite/Auth/Hash/Md5.php b/src/Appwrite/Auth/Hash/Md5.php index 0f6fe5c30d..8ade3dd5e2 100644 --- a/src/Appwrite/Auth/Hash/Md5.php +++ b/src/Appwrite/Auth/Hash/Md5.php @@ -12,7 +12,8 @@ use Appwrite\Auth\Hash; class Md5 extends Hash { /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -21,9 +22,10 @@ class Md5 extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { diff --git a/src/Appwrite/Auth/Hash/Phpass.php b/src/Appwrite/Auth/Hash/Phpass.php index ded4e407ff..187e4a27a6 100644 --- a/src/Appwrite/Auth/Hash/Phpass.php +++ b/src/Appwrite/Auth/Hash/Phpass.php @@ -39,7 +39,6 @@ class Phpass extends Hash * Alphabet used in itoa64 conversions. * * @var string - * * @since 0.1.0 */ protected string $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; @@ -60,7 +59,8 @@ class Phpass extends Hash } /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -68,7 +68,7 @@ class Phpass extends Hash $options = $this->getDefaultOptions(); $random = ''; - if (CRYPT_BLOWFISH === 1 && ! $options['portable_hashes']) { + if (CRYPT_BLOWFISH === 1 && !$options['portable_hashes']) { $random = $this->getRandomBytes(16, $options); $hash = crypt($password, $this->gensaltBlowfish($random, $options)); if (strlen($hash) === 60) { @@ -92,9 +92,10 @@ class Phpass extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -113,16 +114,15 @@ class Phpass extends Hash } /** - * @param int $count - * @return string $output + * @param int $count * + * @return String $output * @since 0.1.0 - * * @throws Exception Thows an Exception if the $count parameter is not a positive integer. */ protected function getRandomBytes(int $count, array $options): string { - if (! is_int($count) || $count < 1) { + if (!is_int($count) || $count < 1) { throw new \Exception('Argument count must be a positive integer'); } $output = ''; @@ -135,7 +135,7 @@ class Phpass extends Hash $output = ''; for ($i = 0; $i < $count; $i += 16) { - $options['iteration_count_log2'] = md5(microtime().$options['iteration_count_log2']); + $options['iteration_count_log2'] = md5(microtime() . $options['iteration_count_log2']); $output .= md5($options['iteration_count_log2'], true); } @@ -146,48 +146,47 @@ class Phpass extends Hash } /** - * @param string $input - * @param int $count - * @return string $output + * @param String $input + * @param int $count * + * @return String $output * @since 0.1.0 - * * @throws Exception Thows an Exception if the $count parameter is not a positive integer. */ protected function encode64($input, $count) { - if (! is_int($count) || $count < 1) { + if (!is_int($count) || $count < 1) { throw new \Exception('Argument count must be a positive integer'); } $output = ''; $i = 0; do { $value = ord($input[$i++]); - $output .= $this->itoa64[$value & 0x3F]; + $output .= $this->itoa64[$value & 0x3f]; if ($i < $count) { $value |= ord($input[$i]) << 8; } - $output .= $this->itoa64[($value >> 6) & 0x3F]; + $output .= $this->itoa64[($value >> 6) & 0x3f]; if ($i++ >= $count) { break; } if ($i < $count) { $value |= ord($input[$i]) << 16; } - $output .= $this->itoa64[($value >> 12) & 0x3F]; + $output .= $this->itoa64[($value >> 12) & 0x3f]; if ($i++ >= $count) { break; } - $output .= $this->itoa64[($value >> 18) & 0x3F]; + $output .= $this->itoa64[($value >> 18) & 0x3f]; } while ($i < $count); return $output; } /** - * @param string $input - * @return string $output + * @param String $input * + * @return String $output * @since 0.1.0 */ private function gensaltPrivate($input, $options) @@ -200,10 +199,10 @@ class Phpass extends Hash } /** - * @param string $password - * @param string $setting - * @return string $output + * @param String $password + * @param String $setting * + * @return String $output * @since 0.1.0 */ private function cryptPrivate($password, $setting) @@ -234,9 +233,9 @@ class Phpass extends Hash * consequently in lower iteration counts and hashes that are * quicker to crack (by non-PHP code). */ - $hash = md5($salt.$password, true); + $hash = md5($salt . $password, true); do { - $hash = md5($hash.$password, true); + $hash = md5($hash . $password, true); } while (--$count); $output = substr($setting, 0, 12); $output .= $this->encode64($hash, 16); @@ -245,9 +244,9 @@ class Phpass extends Hash } /** - * @param string $input - * @return string $output + * @param String $input * + * @return String $output * @since 0.1.0 */ private function gensaltBlowfish($input, $options) @@ -279,11 +278,11 @@ class Phpass extends Hash $c2 = ord($input[$i++]); $c1 |= $c2 >> 4; $output .= $itoa64[$c1]; - $c1 = ($c2 & 0x0F) << 2; + $c1 = ($c2 & 0x0f) << 2; $c2 = ord($input[$i++]); $c1 |= $c2 >> 6; $output .= $itoa64[$c1]; - $output .= $itoa64[$c2 & 0x3F]; + $output .= $itoa64[$c2 & 0x3f]; } while (1); return $output; diff --git a/src/Appwrite/Auth/Hash/Scrypt.php b/src/Appwrite/Auth/Hash/Scrypt.php index 8c50c16341..821b1fba69 100644 --- a/src/Appwrite/Auth/Hash/Scrypt.php +++ b/src/Appwrite/Auth/Hash/Scrypt.php @@ -17,7 +17,8 @@ use Appwrite\Auth\Hash; class Scrypt extends Hash { /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -28,9 +29,10 @@ class Scrypt extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -44,6 +46,6 @@ class Scrypt extends Hash */ public function getDefaultOptions(): array { - return ['costCpu' => 8, 'costMemory' => 14, 'costParallel' => 1, 'length' => 64]; + return [ 'costCpu' => 8, 'costMemory' => 14, 'costParallel' => 1, 'length' => 64 ]; } } diff --git a/src/Appwrite/Auth/Hash/Scryptmodified.php b/src/Appwrite/Auth/Hash/Scryptmodified.php index 9260913aed..2d1cd4f165 100644 --- a/src/Appwrite/Auth/Hash/Scryptmodified.php +++ b/src/Appwrite/Auth/Hash/Scryptmodified.php @@ -16,7 +16,8 @@ use Appwrite\Auth\Hash; class Scryptmodified extends Hash { /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -32,9 +33,10 @@ class Scryptmodified extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -48,7 +50,7 @@ class Scryptmodified extends Hash */ public function getDefaultOptions(): array { - return []; + return [ ]; } private function generateDerivedKey(string $password) @@ -58,7 +60,7 @@ class Scryptmodified extends Hash $saltBytes = \base64_decode($options['salt']); $saltSeparatorBytes = \base64_decode($options['saltSeparator']); - $derivedKey = \scrypt(\utf8_encode($password), $saltBytes.$saltSeparatorBytes, 16384, 8, 1, 64); + $derivedKey = \scrypt(\utf8_encode($password), $saltBytes . $saltSeparatorBytes, 16384, 8, 1, 64); $derivedKey = \hex2bin($derivedKey); return $derivedKey; diff --git a/src/Appwrite/Auth/Hash/Sha.php b/src/Appwrite/Auth/Hash/Sha.php index 331c4fe6f2..c2ae3b52c1 100644 --- a/src/Appwrite/Auth/Hash/Sha.php +++ b/src/Appwrite/Auth/Hash/Sha.php @@ -16,7 +16,8 @@ use Appwrite\Auth\Hash; class Sha extends Hash { /** - * @param string $password Input password to hash + * @param string $password Input password to hash + * * @return string hash */ public function hash(string $password): string @@ -27,9 +28,10 @@ class Sha extends Hash } /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * @return bool true if password matches hash + * @param string $password Input password to validate + * @param string $hash Hash to verify password against + * + * @return boolean true if password matches hash */ public function verify(string $password, string $hash): bool { @@ -43,6 +45,6 @@ class Sha extends Hash */ public function getDefaultOptions(): array { - return ['version' => 'sha3-512']; + return [ 'version' => 'sha3-512' ]; } } diff --git a/src/Appwrite/Auth/OAuth2.php b/src/Appwrite/Auth/OAuth2.php index 37f6416fb5..c737e183f8 100644 --- a/src/Appwrite/Auth/OAuth2.php +++ b/src/Appwrite/Auth/OAuth2.php @@ -34,11 +34,11 @@ abstract class OAuth2 /** * OAuth2 constructor. * - * @param string $appId - * @param string $appSecret - * @param string $callback - * @param array $state - * @param array $scopes + * @param string $appId + * @param string $appSecret + * @param string $callback + * @param array $state + * @param array $scopes */ public function __construct(string $appId, string $appSecret, string $callback, array $state = [], array $scopes = []) { @@ -62,25 +62,29 @@ abstract class OAuth2 abstract public function getLoginURL(): string; /** - * @param string $code + * @param string $code + * * @return array */ abstract protected function getTokens(string $code): array; /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ abstract public function refreshTokens(string $refreshToken): array; /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ abstract public function getUserID(string $accessToken): string; /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ abstract public function getUserEmail(string $accessToken): string; @@ -88,25 +92,28 @@ abstract class OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ abstract public function isEmailVerified(string $accessToken): bool; /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ abstract public function getUserName(string $accessToken): string; /** * @param $scope + * * @return $this */ protected function addScope(string $scope): OAuth2 { // Add a scope to the scopes array if it isn't already present - if (! \in_array($scope, $this->scopes)) { + if (!\in_array($scope, $this->scopes)) { $this->scopes[] = $scope; } @@ -122,7 +129,8 @@ abstract class OAuth2 } /** - * @param string $code + * @param string $code + * * @return string */ public function getAccessToken(string $code): string @@ -133,7 +141,8 @@ abstract class OAuth2 } /** - * @param string $code + * @param string $code + * * @return string */ public function getRefreshToken(string $code): string @@ -144,7 +153,8 @@ abstract class OAuth2 } /** - * @param string $code + * @param string $code + * * @return string */ public function getAccessTokenExpiry(string $code): int @@ -159,6 +169,7 @@ abstract class OAuth2 // json_decoding /** * @param $state + * * @return array */ public function parseState(string $state) @@ -167,10 +178,11 @@ abstract class OAuth2 } /** - * @param string $method - * @param string $url - * @param array $headers - * @param string $payload + * @param string $method + * @param string $url + * @param array $headers + * @param string $payload + * * @return string */ protected function request(string $method, string $url = '', array $headers = [], string $payload = ''): string @@ -182,11 +194,11 @@ abstract class OAuth2 \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); \curl_setopt($ch, CURLOPT_USERAGENT, 'Appwrite OAuth2'); - if (! empty($payload)) { + if (!empty($payload)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); } - $headers[] = 'Content-length: '.\strlen($payload); + $headers[] = 'Content-length: ' . \strlen($payload); \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Send the request & save response to $response @@ -200,6 +212,6 @@ abstract class OAuth2 throw new Exception($response, $code); } - return (string) $response; + return (string)$response; } } diff --git a/src/Appwrite/Auth/OAuth2/Amazon.php b/src/Appwrite/Auth/OAuth2/Amazon.php index c2cdedf2f1..d1d2cb5a38 100644 --- a/src/Appwrite/Auth/OAuth2/Amazon.php +++ b/src/Appwrite/Auth/OAuth2/Amazon.php @@ -25,7 +25,7 @@ class Amazon extends OAuth2 * @var array */ protected array $scopes = [ - 'profile', + "profile" ]; /** @@ -37,7 +37,8 @@ class Amazon extends OAuth2 } /** - * @param string $state + * @param string $state + * * @return array */ public function parseState(string $state) @@ -45,22 +46,24 @@ class Amazon extends OAuth2 return \json_decode(\html_entity_decode($state), true); } + /** * @return string */ public function getLoginURL(): string { - return 'https://www.amazon.com/ap/oa?'.\http_build_query([ + return 'https://www.amazon.com/ap/oa?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), - 'redirect_uri' => $this->callback, + 'redirect_uri' => $this->callback ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -76,7 +79,7 @@ class Amazon extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -85,7 +88,8 @@ class Amazon extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -99,7 +103,7 @@ class Amazon extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, + 'refresh_token' => $refreshToken ]) ), true); @@ -111,7 +115,8 @@ class Amazon extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -122,7 +127,8 @@ class Amazon extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -137,18 +143,20 @@ class Amazon extends OAuth2 * * If present, the email is verified. This was verfied through a manual Amazon sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -159,16 +167,16 @@ class Amazon extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://api.amazon.com/user/profile?access_token='.\urlencode($accessToken)); + $user = $this->request('GET', 'https://api.amazon.com/user/profile?access_token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); } - return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Apple.php b/src/Appwrite/Auth/OAuth2/Apple.php index 27f41543ae..2abf61c947 100644 --- a/src/Appwrite/Auth/OAuth2/Apple.php +++ b/src/Appwrite/Auth/OAuth2/Apple.php @@ -24,8 +24,8 @@ class Apple extends OAuth2 * @var array */ protected array $scopes = [ - 'name', - 'email', + "name", + "email" ]; /** @@ -46,18 +46,19 @@ class Apple extends OAuth2 */ public function getLoginURL(): string { - return 'https://appleid.apple.com/auth/authorize?'.\http_build_query([ + return 'https://appleid.apple.com/auth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'response_type' => 'code', 'response_mode' => 'form_post', - 'scope' => \implode(' ', $this->getScopes()), + 'scope' => \implode(' ', $this->getScopes()) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -85,7 +86,8 @@ class Apple extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -114,7 +116,8 @@ class Apple extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -123,7 +126,8 @@ class Apple extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -136,7 +140,8 @@ class Apple extends OAuth2 * * @link https://developer.apple.com/forums/thread/121411 * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -149,14 +154,15 @@ class Apple extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string { if ( isset($this->claims['email']) && - ! empty($this->claims['email']) && + !empty($this->claims['email']) && isset($this->claims['email_verified']) && $this->claims['email_verified'] === 'true' ) { @@ -177,7 +183,7 @@ class Apple extends OAuth2 $keyfile = (isset($secret['p8'])) ? $secret['p8'] : ''; // Your p8 Key file $keyID = (isset($secret['keyID'])) ? $secret['keyID'] : ''; // Your Key ID $teamID = (isset($secret['teamID'])) ? $secret['teamID'] : ''; // Your Team ID (see Developer Portal) - $bundleID = $this->appID; // Your Bundle ID + $bundleID = $this->appID; // Your Bundle ID $headers = [ 'alg' => 'ES256', @@ -194,21 +200,22 @@ class Apple extends OAuth2 $pkey = \openssl_pkey_get_private($keyfile); - $payload = $this->encode(\json_encode($headers)).'.'.$this->encode(\json_encode($claims)); + $payload = $this->encode(\json_encode($headers)) . '.' . $this->encode(\json_encode($claims)); $signature = ''; $success = \openssl_sign($payload, $signature, $pkey, OPENSSL_ALGO_SHA256); - if (! $success) { + if (!$success) { return ''; } - return $payload.'.'.$this->encode($this->fromDER($signature, 64)); + return $payload . '.' . $this->encode($this->fromDER($signature, 64)); } /** - * @param string $data + * @param string $data + * * @return string */ protected function encode($data): string @@ -217,7 +224,7 @@ class Apple extends OAuth2 } /** - * @param string $data + * @param string $data */ protected function retrievePositiveInteger(string $data): string { @@ -229,8 +236,8 @@ class Apple extends OAuth2 } /** - * @param string $der - * @param int $partLength + * @param string $der + * @param int $partLength */ protected function fromDER(string $der, int $partLength): string { @@ -263,6 +270,6 @@ class Apple extends OAuth2 $S = $this->retrievePositiveInteger(\mb_substr($hex, 4, $Sl * 2, '8bit')); $S = \str_pad($S, $partLength, '0', STR_PAD_LEFT); - return \pack('H*', $R.$S); + return \pack('H*', $R . $S); } } diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index e2615017bd..eba7d18b5f 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -16,7 +16,7 @@ class Auth0 extends OAuth2 'openid', 'profile', 'email', - 'offline_access', + 'offline_access' ]; /** @@ -42,17 +42,18 @@ class Auth0 extends OAuth2 */ public function getLoginURL(): string { - return 'https://'.$this->getAuth0Domain().'/authorize?'.\http_build_query([ + return 'https://' . $this->getAuth0Domain() . '/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -61,7 +62,7 @@ class Auth0 extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://'.$this->getAuth0Domain().'/oauth/token', + 'https://' . $this->getAuth0Domain() . '/oauth/token', $headers, \http_build_query([ 'code' => $code, @@ -69,7 +70,7 @@ class Auth0 extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -77,8 +78,10 @@ class Auth0 extends OAuth2 return $this->tokens; } + /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -86,13 +89,13 @@ class Auth0 extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://'.$this->getAuth0Domain().'/oauth/token', + 'https://' . $this->getAuth0Domain() . '/oauth/token', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -104,7 +107,8 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -115,7 +119,8 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -130,7 +135,8 @@ class Auth0 extends OAuth2 * * @link https://auth0.com/docs/api/authentication?javascript#user-profile * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -145,7 +151,8 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -156,14 +163,15 @@ class Auth0 extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; - $user = $this->request('GET', 'https://'.$this->getAuth0Domain().'/userinfo', $headers); + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $user = $this->request('GET', 'https://' . $this->getAuth0Domain() . '/userinfo', $headers); $this->user = \json_decode($user, true); } @@ -206,7 +214,6 @@ class Auth0 extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } - return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Authentik.php b/src/Appwrite/Auth/OAuth2/Authentik.php index 8a6b13cdef..16822e2c9f 100644 --- a/src/Appwrite/Auth/OAuth2/Authentik.php +++ b/src/Appwrite/Auth/OAuth2/Authentik.php @@ -16,7 +16,7 @@ class Authentik extends OAuth2 'openid', 'profile', 'email', - 'offline_access', + 'offline_access' ]; /** @@ -42,17 +42,18 @@ class Authentik extends OAuth2 */ public function getLoginURL(): string { - return 'https://'.$this->getAuthentikDomain().'/application/o/authorize?'.\http_build_query([ + return 'https://' . $this->getAuthentikDomain() . '/application/o/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -61,7 +62,7 @@ class Authentik extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://'.$this->getAuthentikDomain().'/application/o/token/', + 'https://' . $this->getAuthentikDomain() . '/application/o/token/', $headers, \http_build_query([ 'code' => $code, @@ -69,16 +70,17 @@ class Authentik extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } - return $this->tokens; } + /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -86,13 +88,13 @@ class Authentik extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://'.$this->getAuthentikDomain().'/application/o/token/', + 'https://' . $this->getAuthentikDomain() . '/application/o/token/', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -104,7 +106,8 @@ class Authentik extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -119,7 +122,8 @@ class Authentik extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -136,7 +140,8 @@ class Authentik extends OAuth2 /** * Check if the User email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -151,7 +156,8 @@ class Authentik extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -165,15 +171,16 @@ class Authentik extends OAuth2 return ''; } - /** - * @param string $accessToken + /** + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; - $user = $this->request('GET', 'https://'.$this->getAuthentikDomain().'/application/o/userinfo/', $headers); + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $user = $this->request('GET', 'https://' . $this->getAuthentikDomain() . '/application/o/userinfo/', $headers); $this->user = \json_decode($user, true); } @@ -192,7 +199,7 @@ class Authentik extends OAuth2 return $secret['clientSecret'] ?? ''; } - /** + /** * Extracts the authentik Domain from the JSON stored in appSecret * * @return string @@ -200,7 +207,6 @@ class Authentik extends OAuth2 protected function getAuthentikDomain(): string { $secret = $this->getAppSecret(); - return $secret['authentikDomain'] ?? ''; } @@ -216,7 +222,6 @@ class Authentik extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } - return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Autodesk.php b/src/Appwrite/Auth/OAuth2/Autodesk.php index 071eee7dcb..0b268ead3b 100644 --- a/src/Appwrite/Auth/OAuth2/Autodesk.php +++ b/src/Appwrite/Auth/OAuth2/Autodesk.php @@ -36,17 +36,18 @@ class Autodesk extends OAuth2 */ public function getLoginURL(): string { - return 'https://developer.api.autodesk.com/authentication/v1/authorize?'.\http_build_query([ + return 'https://developer.api.autodesk.com/authentication/v1/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), 'redirect_uri' => $this->callback, - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -62,7 +63,7 @@ class Autodesk extends OAuth2 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'code' => $code, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ); @@ -73,7 +74,8 @@ class Autodesk extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -103,7 +105,8 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -114,7 +117,8 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -129,7 +133,8 @@ class Autodesk extends OAuth2 * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -144,7 +149,8 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -155,13 +161,14 @@ class Autodesk extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; $user = $this->request('GET', 'https://developer.api.autodesk.com/userprofile/v1/users/@me', $headers); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Bitbucket.php b/src/Appwrite/Auth/OAuth2/Bitbucket.php index eea5af4c1b..361bc22b65 100644 --- a/src/Appwrite/Auth/OAuth2/Bitbucket.php +++ b/src/Appwrite/Auth/OAuth2/Bitbucket.php @@ -37,7 +37,7 @@ class Bitbucket extends OAuth2 */ public function getLoginURL(): string { - return 'https://bitbucket.org/site/oauth2/authorize?'.\http_build_query([ + return 'https://bitbucket.org/site/oauth2/authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), @@ -46,7 +46,8 @@ class Bitbucket extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -62,7 +63,7 @@ class Bitbucket extends OAuth2 'code' => $code, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -71,7 +72,8 @@ class Bitbucket extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -85,7 +87,7 @@ class Bitbucket extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, + 'refresh_token' => $refreshToken ]) ), true); @@ -97,7 +99,8 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -108,7 +111,8 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -121,7 +125,8 @@ class Bitbucket extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -136,7 +141,8 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -147,16 +153,17 @@ class Bitbucket extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://api.bitbucket.org/2.0/user?access_token='.\urlencode($accessToken)); + $user = $this->request('GET', 'https://api.bitbucket.org/2.0/user?access_token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); - $emails = $this->request('GET', 'https://api.bitbucket.org/2.0/user/emails?access_token='.\urlencode($accessToken)); + $emails = $this->request('GET', 'https://api.bitbucket.org/2.0/user/emails?access_token=' . \urlencode($accessToken)); $emails = \json_decode($emails, true); if (isset($emails['values'])) { foreach ($emails['values'] as $email) { @@ -168,7 +175,6 @@ class Bitbucket extends OAuth2 } } } - return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Bitly.php b/src/Appwrite/Auth/OAuth2/Bitly.php index b5521cad39..290876a8cb 100644 --- a/src/Appwrite/Auth/OAuth2/Bitly.php +++ b/src/Appwrite/Auth/OAuth2/Bitly.php @@ -47,16 +47,17 @@ class Bitly extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'authorize?'. + return $this->endpoint . 'authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -64,14 +65,14 @@ class Bitly extends OAuth2 if (empty($this->tokens)) { $response = $this->request( 'POST', - $this->resourceEndpoint.'oauth/access_token', - ['Content-Type: application/x-www-form-urlencoded'], + $this->resourceEndpoint . 'oauth/access_token', + ["Content-Type: application/x-www-form-urlencoded"], \http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'code' => $code, - 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state), + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "code" => $code, + "redirect_uri" => $this->callback, + "state" => \json_encode($this->state) ]) ); @@ -84,20 +85,21 @@ class Bitly extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $response = $this->request( 'POST', - $this->resourceEndpoint.'oauth/access_token', - ['Content-Type: application/x-www-form-urlencoded'], + $this->resourceEndpoint . 'oauth/access_token', + ["Content-Type: application/x-www-form-urlencoded"], \http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "refresh_token" => $refreshToken, + 'grant_type' => 'refresh_token' ]) ); @@ -113,7 +115,8 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -124,7 +127,8 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -147,7 +151,8 @@ class Bitly extends OAuth2 * * @link https://dev.bitly.com/api-reference#getUser * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -156,7 +161,8 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -167,18 +173,19 @@ class Bitly extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) { $headers = [ - 'Authorization: Bearer '.\urlencode($accessToken), - 'Accept: application/json', + 'Authorization: Bearer ' . \urlencode($accessToken), + "Accept: application/json" ]; if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', $this->resourceEndpoint.'v4/user', $headers), true); + $this->user = \json_decode($this->request('GET', $this->resourceEndpoint . "v4/user", $headers), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Box.php b/src/Appwrite/Auth/OAuth2/Box.php index 5d2c5e2b38..e88c165833 100644 --- a/src/Appwrite/Auth/OAuth2/Box.php +++ b/src/Appwrite/Auth/OAuth2/Box.php @@ -49,7 +49,7 @@ class Box extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint.'authorize?'. + $url = $this->endpoint . 'authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, @@ -62,7 +62,8 @@ class Box extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -71,15 +72,15 @@ class Box extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'token', + $this->endpoint . 'token', $headers, \http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'code' => $code, - 'grant_type' => 'authorization_code', - 'scope' => \implode(',', $this->getScopes()), - 'redirect_uri' => $this->callback, + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "code" => $code, + "grant_type" => "authorization_code", + "scope" => \implode(',', $this->getScopes()), + "redirect_uri" => $this->callback ]) ), true); } @@ -88,7 +89,8 @@ class Box extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -96,13 +98,13 @@ class Box extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'token', + $this->endpoint . 'token', $headers, \http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "refresh_token" => $refreshToken, + "grant_type" => "refresh_token", ]) ), true); @@ -114,7 +116,8 @@ class Box extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -125,7 +128,8 @@ class Box extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -140,18 +144,20 @@ class Box extends OAuth2 * * If present, the email is verified. This was verfied through a manual Box sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -162,18 +168,19 @@ class Box extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { $header = [ - 'Authorization: Bearer '.\urlencode($accessToken), + 'Authorization: Bearer ' . \urlencode($accessToken), ]; if (empty($this->user)) { $user = $this->request( 'GET', - $this->resourceEndpoint.'me', + $this->resourceEndpoint . 'me', $header ); $this->user = \json_decode($user, true); diff --git a/src/Appwrite/Auth/OAuth2/Dailymotion.php b/src/Appwrite/Auth/OAuth2/Dailymotion.php index 5ead308fbe..0fc90e3ca1 100644 --- a/src/Appwrite/Auth/OAuth2/Dailymotion.php +++ b/src/Appwrite/Auth/OAuth2/Dailymotion.php @@ -24,7 +24,7 @@ class Dailymotion extends OAuth2 */ protected array $scopes = [ 'userinfo', - 'email', + 'email' ]; /** @@ -34,7 +34,7 @@ class Dailymotion extends OAuth2 'email', 'id', 'fullname', - 'verified', + 'verified' ]; /** @@ -68,20 +68,21 @@ class Dailymotion extends OAuth2 */ public function getLoginURL(): string { - $url = $this->authEndpoint.'?'. + $url = $this->authEndpoint . '?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'state' => \json_encode($this->state), 'redirect_uri' => $this->callback, - 'scope' => \implode(' ', $this->getScopes()), + 'scope' => \implode(' ', $this->getScopes()) ]); return $url; } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -89,31 +90,33 @@ class Dailymotion extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', - ['Content-Type: application/x-www-form-urlencoded'], + $this->endpoint . '/oauth/token', + ["Content-Type: application/x-www-form-urlencoded"], \http_build_query([ 'grant_type' => 'authorization_code', - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'redirect_uri' => $this->callback, + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "redirect_uri" => $this->callback, 'code' => $code, 'scope' => \implode(' ', $this->getScopes()), ]) ), true); } - return $this->tokens; } + /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { + $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -127,11 +130,13 @@ class Dailymotion extends OAuth2 $this->tokens['refresh_token'] = $refreshToken; } + return $this->tokens; } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -144,7 +149,8 @@ class Dailymotion extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -160,7 +166,8 @@ class Dailymotion extends OAuth2 * * @link https://developers.dailymotion.com/api/#user-fields * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -171,20 +178,23 @@ class Dailymotion extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string { $user = $this->getUser($accessToken); + $username = $user['fullname'] ?? ''; return $username; } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array @@ -192,8 +202,8 @@ class Dailymotion extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - $this->endpoint.'/user/me?fields='.\implode(',', $this->getFields()), - ['Authorization: Bearer '.\urlencode($accessToken)], + $this->endpoint . '/user/me?fields=' . \implode(',', $this->getFields()), + ['Authorization: Bearer ' . \urlencode($accessToken)], ); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Discord.php b/src/Appwrite/Auth/OAuth2/Discord.php index b98d5bdc0c..b77ce6a236 100644 --- a/src/Appwrite/Auth/OAuth2/Discord.php +++ b/src/Appwrite/Auth/OAuth2/Discord.php @@ -28,8 +28,8 @@ class Discord extends OAuth2 * @var array */ protected array $scopes = [ - 'identify', - 'email', + 'identify', + 'email' ]; /** @@ -45,20 +45,21 @@ class Discord extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint.'/oauth2/authorize?'. + $url = $this->endpoint . '/oauth2/authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'redirect_uri' => $this->callback, + 'redirect_uri' => $this->callback ]); return $url; } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -66,7 +67,7 @@ class Discord extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth2/token', + $this->endpoint . '/oauth2/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', @@ -74,7 +75,7 @@ class Discord extends OAuth2 'redirect_uri' => $this->callback, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'scope' => \implode(' ', $this->getScopes()), + 'scope' => \implode(' ', $this->getScopes()) ]) ), true); } @@ -83,14 +84,15 @@ class Discord extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth2/token', + $this->endpoint . '/oauth2/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -108,7 +110,8 @@ class Discord extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -119,7 +122,8 @@ class Discord extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -134,7 +138,8 @@ class Discord extends OAuth2 * * @link https://discord.com/developers/docs/resources/user * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -149,7 +154,8 @@ class Discord extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -160,7 +166,8 @@ class Discord extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array @@ -168,8 +175,8 @@ class Discord extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - $this->endpoint.'/users/@me', - ['Authorization: Bearer '.\urlencode($accessToken)] + $this->endpoint . '/users/@me', + ['Authorization: Bearer ' . \urlencode($accessToken)] ); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Disqus.php b/src/Appwrite/Auth/OAuth2/Disqus.php index eb657298cd..58b7f48914 100644 --- a/src/Appwrite/Auth/OAuth2/Disqus.php +++ b/src/Appwrite/Auth/OAuth2/Disqus.php @@ -45,20 +45,21 @@ class Disqus extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint.'oauth/2.0/authorize/?'. + $url = $this->endpoint . 'oauth/2.0/authorize/?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'state' => \json_encode($this->state), 'redirect_uri' => $this->callback, - 'scope' => \implode(',', $this->getScopes()), + 'scope' => \implode(',', $this->getScopes()) ]); return $url; } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -66,7 +67,7 @@ class Disqus extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'oauth/2.0/access_token/', + $this->endpoint . 'oauth/2.0/access_token/', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', @@ -78,19 +79,19 @@ class Disqus extends OAuth2 ]) ), true); } - return $this->tokens; } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'oauth/2.0/access_token/?', + $this->endpoint . 'oauth/2.0/access_token/?', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -103,12 +104,12 @@ class Disqus extends OAuth2 if (empty($this->tokens['refresh_token'])) { $this->tokens['refresh_token'] = $refreshToken; } - return $this->tokens; } /** - * @param string $token + * @param string $token + * * @return string */ public function getUserID(string $accessToken): string @@ -121,7 +122,8 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -134,11 +136,13 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { + // Look out for the change in their enpoint. // It's in Beta so they may provide a parameter in the future. // https://disqus.com/api/docs/users/details/ @@ -147,7 +151,8 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -160,7 +165,8 @@ class Disqus extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array @@ -168,10 +174,10 @@ class Disqus extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - $this->endpoint.'3.0/users/details.json?'.\http_build_query([ + $this->endpoint . '3.0/users/details.json?' . \http_build_query([ 'access_token' => $accessToken, 'api_key' => $this->appID, - 'api_secret' => $this->appSecret, + 'api_secret' => $this->appSecret ]), ); $this->user = \json_decode($user, true)['response']; diff --git a/src/Appwrite/Auth/OAuth2/Dropbox.php b/src/Appwrite/Auth/OAuth2/Dropbox.php index 156f93e0ee..ff30b87d8a 100644 --- a/src/Appwrite/Auth/OAuth2/Dropbox.php +++ b/src/Appwrite/Auth/OAuth2/Dropbox.php @@ -38,16 +38,17 @@ class Dropbox extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.dropbox.com/oauth2/authorize?'.\http_build_query([ + return 'https://www.dropbox.com/oauth2/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -63,7 +64,7 @@ class Dropbox extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -72,7 +73,8 @@ class Dropbox extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -86,7 +88,7 @@ class Dropbox extends OAuth2 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -98,7 +100,8 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -109,7 +112,8 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -124,7 +128,8 @@ class Dropbox extends OAuth2 * * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -139,7 +144,8 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -150,13 +156,14 @@ class Dropbox extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; $user = $this->request('POST', 'https://api.dropboxapi.com/2/users/get_current_account', $headers); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Etsy.php b/src/Appwrite/Auth/OAuth2/Etsy.php index 7316cdc1d5..7ff16fcb78 100644 --- a/src/Appwrite/Auth/OAuth2/Etsy.php +++ b/src/Appwrite/Auth/OAuth2/Etsy.php @@ -30,8 +30,8 @@ class Etsy extends OAuth2 * @var array */ protected array $scopes = [ - 'email_r', - 'profile_r', + "email_r", + "profile_r", ]; /** @@ -64,7 +64,7 @@ class Etsy extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.etsy.com/oauth/connect/oauth/authorize?'.\http_build_query([ + return 'https://www.etsy.com/oauth/connect/oauth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', @@ -76,7 +76,8 @@ class Etsy extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -86,7 +87,7 @@ class Etsy extends OAuth2 $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', $headers, \http_build_query([ 'grant_type' => 'authorization_code', @@ -102,7 +103,8 @@ class Etsy extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -111,7 +113,7 @@ class Etsy extends OAuth2 $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', $headers, \http_build_query([ 'grant_type' => 'refresh_token', @@ -129,6 +131,7 @@ class Etsy extends OAuth2 /** * @param $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -140,6 +143,7 @@ class Etsy extends OAuth2 /** * @param $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -152,18 +156,20 @@ class Etsy extends OAuth2 * * OAuth is only allowed if account has been verified through Etsy, itself. * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** * @param $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -172,20 +178,21 @@ class Etsy extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { - if (! empty($this->user)) { + if (!empty($this->user)) { return $this->user; } - $headers = ['Authorization: Bearer '.$accessToken]; + $headers = ['Authorization: Bearer ' . $accessToken]; $this->user = \json_decode($this->request( 'GET', - 'https://api.etsy.com/v3/application/users/'.$this->getUserID($accessToken), + 'https://api.etsy.com/v3/application/users/' . $this->getUserID($accessToken), ), true); return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Exception.php b/src/Appwrite/Auth/OAuth2/Exception.php index eddab9d400..3d5b79d3b0 100644 --- a/src/Appwrite/Auth/OAuth2/Exception.php +++ b/src/Appwrite/Auth/OAuth2/Exception.php @@ -7,9 +7,7 @@ use Appwrite\Extend\Exception as AppwriteException; class Exception extends AppwriteException { protected string $response = ''; - protected string $error = ''; - protected string $errorDescription = ''; public function __construct(string $response = '', int $code = 0, \Throwable $previous = null) @@ -21,11 +19,11 @@ class Exception extends AppwriteException if (\is_array($decoded['error'])) { $this->error = $decoded['error']['status']; $this->errorDescription = $decoded['error']['message']; - $this->message = $this->error.': '.$this->errorDescription; + $this->message = $this->error . ': ' . $this->errorDescription; } else { $this->error = $decoded['error']; $this->errorDescription = $decoded['error_description']; - $this->message = $this->error.': '.$this->errorDescription; + $this->message = $this->error . ': ' . $this->errorDescription; } } $type = match ($code) { diff --git a/src/Appwrite/Auth/OAuth2/Facebook.php b/src/Appwrite/Auth/OAuth2/Facebook.php index 9b10f3be80..90fe8e7388 100644 --- a/src/Appwrite/Auth/OAuth2/Facebook.php +++ b/src/Appwrite/Auth/OAuth2/Facebook.php @@ -25,7 +25,7 @@ class Facebook extends OAuth2 * @var array */ protected array $scopes = [ - 'email', + 'email' ]; /** @@ -41,16 +41,17 @@ class Facebook extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.facebook.com/'.$this->version.'/dialog/oauth?'.\http_build_query([ + return 'https://www.facebook.com/' . $this->version . '/dialog/oauth?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -58,11 +59,11 @@ class Facebook extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'GET', - 'https://graph.facebook.com/'.$this->version.'/oauth/access_token?'.\http_build_query([ + 'https://graph.facebook.com/' . $this->version . '/oauth/access_token?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, - 'code' => $code, + 'code' => $code ]) ), true); } @@ -71,19 +72,20 @@ class Facebook extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'GET', - 'https://graph.facebook.com/'.$this->version.'/oauth/access_token?'.\http_build_query([ + 'https://graph.facebook.com/' . $this->version . '/oauth/access_token?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -95,7 +97,8 @@ class Facebook extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -106,7 +109,8 @@ class Facebook extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -121,18 +125,20 @@ class Facebook extends OAuth2 * * If present, the email is verified. This was verfied through a manual Facebook sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -143,13 +149,14 @@ class Facebook extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://graph.facebook.com/'.$this->version.'/me?fields=email,name&access_token='.\urlencode($accessToken)); + $user = $this->request('GET', 'https://graph.facebook.com/' . $this->version . '/me?fields=email,name&access_token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Firebase.php b/src/Appwrite/Auth/OAuth2/Firebase.php index 96638e83a3..0a813881be 100644 --- a/src/Appwrite/Auth/OAuth2/Firebase.php +++ b/src/Appwrite/Auth/OAuth2/Firebase.php @@ -24,7 +24,7 @@ class Firebase extends OAuth2 'https://www.googleapis.com/auth/datastore', 'https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/identitytoolkit', - 'https://www.googleapis.com/auth/userinfo.profile', + 'https://www.googleapis.com/auth/userinfo.profile' ]; /** @@ -40,7 +40,7 @@ class Firebase extends OAuth2 */ public function getLoginURL(): string { - return 'https://accounts.google.com/o/oauth2/v2/auth?'.\http_build_query([ + return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([ 'access_type' => 'offline', 'client_id' => $this->appID, 'redirect_uri' => $this->callback, @@ -52,7 +52,8 @@ class Firebase extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -67,18 +68,19 @@ class Firebase extends OAuth2 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'code' => $code, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ); - $this->tokens = \json_decode($response, true); + $this->tokens = \json_decode($response, true); } return $this->tokens; } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -91,7 +93,7 @@ class Firebase extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, + 'refresh_token' => $refreshToken ]) ); @@ -106,8 +108,10 @@ class Firebase extends OAuth2 return $this->tokens; } + /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -118,7 +122,8 @@ class Firebase extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -128,12 +133,14 @@ class Firebase extends OAuth2 return $user['email'] ?? ''; } + /** * Check if the OAuth email is verified * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -148,7 +155,8 @@ class Firebase extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -159,7 +167,8 @@ class Firebase extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) @@ -167,7 +176,7 @@ class Firebase extends OAuth2 if (empty($this->user)) { $response = $this->request( 'GET', - 'https://www.googleapis.com/oauth2/v1/userinfo?access_token='.\urlencode($accessToken), + 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' . \urlencode($accessToken), [], ); @@ -179,7 +188,7 @@ class Firebase extends OAuth2 public function getProjects(string $accessToken): array { - $projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer '.\urlencode($accessToken)]); + $projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer ' . \urlencode($accessToken)]); $projects = \json_decode($projects, true); @@ -192,9 +201,9 @@ class Firebase extends OAuth2 public function assignIAMRoles(string $accessToken, string $email, string $projectId) { // Get IAM Roles - $iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/'.$projectId.':getIamPolicy', [ - 'Authorization: Bearer '.\urlencode($accessToken), - 'Content-Type: application/json', + $iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':getIamPolicy', [ + 'Authorization: Bearer ' . \urlencode($accessToken), + 'Content-Type: application/json' ]); $iamRoles = \json_decode($iamRoles, true); @@ -202,23 +211,23 @@ class Firebase extends OAuth2 $iamRoles['bindings'][] = [ 'role' => 'roles/identitytoolkit.admin', 'members' => [ - 'serviceAccount:'.$email, - ], + 'serviceAccount:' . $email + ] ]; $iamRoles['bindings'][] = [ 'role' => 'roles/firebase.admin', 'members' => [ - 'serviceAccount:'.$email, - ], + 'serviceAccount:' . $email + ] ]; // Set IAM Roles - $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/'.$projectId.':setIamPolicy', [ - 'Authorization: Bearer '.\urlencode($accessToken), - 'Content-Type: application/json', + $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':setIamPolicy', [ + 'Authorization: Bearer ' . \urlencode($accessToken), + 'Content-Type: application/json' ], json_encode([ - 'policy' => $iamRoles, + 'policy' => $iamRoles ])); } @@ -227,16 +236,16 @@ class Firebase extends OAuth2 // Create Service Account $response = $this->request( 'POST', - 'https://iam.googleapis.com/v1/projects/'.$projectId.'/serviceAccounts', + 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts', [ - 'Authorization: Bearer '.\urlencode($accessToken), - 'Content-Type: application/json', + 'Authorization: Bearer ' . \urlencode($accessToken), + 'Content-Type: application/json' ], json_encode([ 'accountId' => 'appwrite-migrations', 'serviceAccount' => [ - 'displayName' => 'Appwrite Migrations', - ], + 'displayName' => 'Appwrite Migrations' + ] ]) ); @@ -247,10 +256,10 @@ class Firebase extends OAuth2 // Create Service Account Key $responseKey = $this->request( 'POST', - 'https://iam.googleapis.com/v1/projects/'.$projectId.'/serviceAccounts/'.$response['email'].'/keys', + 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $response['email'] . '/keys', [ - 'Authorization: Bearer '.\urlencode($accessToken), - 'Content-Type: application/json', + 'Authorization: Bearer ' . \urlencode($accessToken), + 'Content-Type: application/json' ] ); diff --git a/src/Appwrite/Auth/OAuth2/Github.php b/src/Appwrite/Auth/OAuth2/Github.php index ab67e17aa0..8b9208fc06 100644 --- a/src/Appwrite/Auth/OAuth2/Github.php +++ b/src/Appwrite/Auth/OAuth2/Github.php @@ -36,16 +36,17 @@ class Github extends OAuth2 */ public function getLoginURL(): string { - return 'https://github.com/login/oauth/authorize?'.\http_build_query([ + return 'https://github.com/login/oauth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -59,7 +60,7 @@ class Github extends OAuth2 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, - 'code' => $code, + 'code' => $code ]) ); @@ -72,7 +73,8 @@ class Github extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -85,7 +87,7 @@ class Github extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, + 'refresh_token' => $refreshToken ]) ); @@ -101,7 +103,8 @@ class Github extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -112,7 +115,8 @@ class Github extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -127,7 +131,8 @@ class Github extends OAuth2 * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -142,7 +147,8 @@ class Github extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -153,7 +159,8 @@ class Github extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserSlug(string $accessToken): string @@ -164,15 +171,16 @@ class Github extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) { if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', 'https://api.github.com/user', ['Authorization: token '.\urlencode($accessToken)]), true); + $this->user = \json_decode($this->request('GET', 'https://api.github.com/user', ['Authorization: token ' . \urlencode($accessToken)]), true); - $emails = $this->request('GET', 'https://api.github.com/user/emails', ['Authorization: token '.\urlencode($accessToken)]); + $emails = $this->request('GET', 'https://api.github.com/user/emails', ['Authorization: token ' . \urlencode($accessToken)]); $emails = \json_decode($emails, true); @@ -189,10 +197,10 @@ class Github extends OAuth2 } } - if (! empty($primaryEmail)) { + if (!empty($primaryEmail)) { $this->user['email'] = $primaryEmail['email']; $this->user['verified'] = $primaryEmail['verified']; - } elseif (! empty($verifiedEmail)) { + } elseif (!empty($verifiedEmail)) { $this->user['email'] = $verifiedEmail['email']; $this->user['verified'] = $verifiedEmail['verified']; } diff --git a/src/Appwrite/Auth/OAuth2/Gitlab.php b/src/Appwrite/Auth/OAuth2/Gitlab.php index f96348c98b..7d98bf1921 100644 --- a/src/Appwrite/Auth/OAuth2/Gitlab.php +++ b/src/Appwrite/Auth/OAuth2/Gitlab.php @@ -23,7 +23,7 @@ class Gitlab extends OAuth2 * @var array */ protected array $scopes = [ - 'read_user', + 'read_user' ]; /** @@ -39,17 +39,18 @@ class Gitlab extends OAuth2 */ public function getLoginURL(): string { - return $this->getEndpoint().'/oauth/authorize?'.\http_build_query([ + return $this->getEndpoint() . '/oauth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -57,12 +58,12 @@ class Gitlab extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->getEndpoint().'/oauth/token?'.\http_build_query([ + $this->getEndpoint() . '/oauth/token?' . \http_build_query([ 'code' => $code, 'client_id' => $this->appID, 'client_secret' => $this->getAppSecret()['clientSecret'], 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -71,18 +72,19 @@ class Gitlab extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->getEndpoint().'/oauth/token?'.\http_build_query([ + $this->getEndpoint() . '/oauth/token?' . \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getAppSecret()['clientSecret'], - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -94,7 +96,8 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -109,7 +112,8 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -124,7 +128,8 @@ class Gitlab extends OAuth2 * * @link https://docs.gitlab.com/ee/api/users.html#list-current-user-for-normal-users * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -139,7 +144,8 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -150,13 +156,14 @@ class Gitlab extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', $this->getEndpoint().'/api/v4/user?access_token='.\urlencode($accessToken)); + $user = $this->request('GET', $this->getEndpoint() . '/api/v4/user?access_token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); } @@ -175,10 +182,10 @@ class Gitlab extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } - return $secret; } + /** * Extracts the Tenant Id from the JSON stored in appSecret. Defaults to 'common' as a fallback * @@ -189,7 +196,6 @@ class Gitlab extends OAuth2 $defaultEndpoint = 'https://gitlab.com'; $secret = $this->getAppSecret(); $endpoint = $secret['endpoint'] ?? $defaultEndpoint; - return empty($endpoint) ? $defaultEndpoint : $endpoint; } } diff --git a/src/Appwrite/Auth/OAuth2/Google.php b/src/Appwrite/Auth/OAuth2/Google.php index c56f1660c4..c6f621b814 100644 --- a/src/Appwrite/Auth/OAuth2/Google.php +++ b/src/Appwrite/Auth/OAuth2/Google.php @@ -22,7 +22,7 @@ class Google extends OAuth2 protected array $scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', - 'openid', + 'openid' ]; /** @@ -48,17 +48,18 @@ class Google extends OAuth2 */ public function getLoginURL(): string { - return 'https://accounts.google.com/o/oauth2/v2/auth?'.\http_build_query([ + return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), 'state' => \json_encode($this->state), - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -66,13 +67,13 @@ class Google extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - 'https://oauth2.googleapis.com/token?'.\http_build_query([ + 'https://oauth2.googleapis.com/token?' . \http_build_query([ 'code' => $code, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'redirect_uri' => $this->callback, 'scope' => null, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -81,18 +82,19 @@ class Google extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - 'https://oauth2.googleapis.com/token?'.\http_build_query([ + 'https://oauth2.googleapis.com/token?' . \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->appSecret, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -104,7 +106,8 @@ class Google extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -115,7 +118,8 @@ class Google extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -130,7 +134,8 @@ class Google extends OAuth2 * * @link https://www.oauth.com/oauth2-servers/signing-in-with-google/verifying-the-user-info/ * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -145,7 +150,8 @@ class Google extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -156,13 +162,14 @@ class Google extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://www.googleapis.com/oauth2/v3/userinfo?access_token='.\urlencode($accessToken)); + $user = $this->request('GET', 'https://www.googleapis.com/oauth2/v3/userinfo?access_token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Linkedin.php b/src/Appwrite/Auth/OAuth2/Linkedin.php index c4e899b5ca..340cab2df0 100644 --- a/src/Appwrite/Auth/OAuth2/Linkedin.php +++ b/src/Appwrite/Auth/OAuth2/Linkedin.php @@ -50,7 +50,7 @@ class Linkedin extends OAuth2 */ public function getLoginURL(): string { - return 'https://www.linkedin.com/oauth/v2/authorization?'.\http_build_query([ + return 'https://www.linkedin.com/oauth/v2/authorization?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'redirect_uri' => $this->callback, @@ -60,7 +60,8 @@ class Linkedin extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -79,12 +80,12 @@ class Linkedin extends OAuth2 ]) ), true); } - return $this->tokens; } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -105,12 +106,12 @@ class Linkedin extends OAuth2 if (empty($this->tokens['refresh_token'])) { $this->tokens['refresh_token'] = $refreshToken; } - return $this->tokens; } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -121,12 +122,13 @@ class Linkedin extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string { - $email = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', ['Authorization: Bearer '.\urlencode($accessToken)]), true); + $email = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', ['Authorization: Bearer ' . \urlencode($accessToken)]), true); return $email['elements'][0]['handle~']['emailAddress'] ?? ''; } @@ -136,18 +138,20 @@ class Linkedin extends OAuth2 * * If present, the email is verified. This was verfied through a manual Linkedin sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -160,20 +164,21 @@ class Linkedin extends OAuth2 } if (isset($user['localizedLastName'])) { - $name = (empty($name)) ? $user['localizedLastName'] : $name.' '.$user['localizedLastName']; + $name = (empty($name)) ? $user['localizedLastName'] : $name . ' ' . $user['localizedLastName']; } return $name; } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) { if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/me', ['Authorization: Bearer '.\urlencode($accessToken)]), true); + $this->user = \json_decode($this->request('GET', 'https://api.linkedin.com/v2/me', ['Authorization: Bearer ' . \urlencode($accessToken)]), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Microsoft.php b/src/Appwrite/Auth/OAuth2/Microsoft.php index 89b77c1925..bc05843b37 100644 --- a/src/Appwrite/Auth/OAuth2/Microsoft.php +++ b/src/Appwrite/Auth/OAuth2/Microsoft.php @@ -25,7 +25,7 @@ class Microsoft extends OAuth2 */ protected array $scopes = [ 'offline_access', - 'user.read', + 'user.read' ]; /** @@ -41,18 +41,19 @@ class Microsoft extends OAuth2 */ public function getLoginURL(): string { - return 'https://login.microsoftonline.com/'.$this->getTenantID().'/oauth2/v2.0/authorize?'.\http_build_query([ + return 'https://login.microsoftonline.com/' . $this->getTenantID() . '/oauth2/v2.0/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), 'response_type' => 'code', - 'response_mode' => 'query', + 'response_mode' => 'query' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -61,7 +62,7 @@ class Microsoft extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://login.microsoftonline.com/'.$this->getTenantID().'/oauth2/v2.0/token', + 'https://login.microsoftonline.com/' . $this->getTenantID() . '/oauth2/v2.0/token', $headers, \http_build_query([ 'code' => $code, @@ -69,7 +70,7 @@ class Microsoft extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -78,7 +79,8 @@ class Microsoft extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -86,13 +88,13 @@ class Microsoft extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://login.microsoftonline.com/'.$this->getTenantID().'/oauth2/v2.0/token', + 'https://login.microsoftonline.com/' . $this->getTenantID() . '/oauth2/v2.0/token', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -104,7 +106,8 @@ class Microsoft extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -115,7 +118,8 @@ class Microsoft extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -130,18 +134,20 @@ class Microsoft extends OAuth2 * * If present, the email is verified. This was verfied through a manual Microsoft sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -152,13 +158,14 @@ class Microsoft extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; $user = $this->request('GET', 'https://graph.microsoft.com/v1.0/me', $headers); $this->user = \json_decode($user, true); } @@ -178,7 +185,6 @@ class Microsoft extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } - return $secret; } diff --git a/src/Appwrite/Auth/OAuth2/Mock.php b/src/Appwrite/Auth/OAuth2/Mock.php index b0b2e3b8d1..d2cb8c1c2a 100644 --- a/src/Appwrite/Auth/OAuth2/Mock.php +++ b/src/Appwrite/Auth/OAuth2/Mock.php @@ -3,6 +3,7 @@ namespace Appwrite\Auth\OAuth2; use Appwrite\Auth\OAuth2; +use Utopia\Exception; class Mock extends OAuth2 { @@ -15,7 +16,7 @@ class Mock extends OAuth2 * @var array */ protected array $scopes = [ - 'email', + 'email' ]; /** @@ -41,16 +42,17 @@ class Mock extends OAuth2 */ public function getLoginURL(): string { - return 'http://localhost/'.$this->version.'/mock/tests/general/oauth2?'.\http_build_query([ + return 'http://localhost/' . $this->version . '/mock/tests/general/oauth2?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -58,12 +60,12 @@ class Mock extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'GET', - 'http://localhost/'.$this->version.'/mock/tests/general/oauth2/token?'. + 'http://localhost/' . $this->version . '/mock/tests/general/oauth2/token?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, - 'code' => $code, + 'code' => $code ]) ), true); } @@ -72,19 +74,20 @@ class Mock extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'GET', - 'http://localhost/'.$this->version.'/mock/tests/general/oauth2/token?'. + 'http://localhost/' . $this->version . '/mock/tests/general/oauth2/token?' . \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -96,7 +99,8 @@ class Mock extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -107,7 +111,8 @@ class Mock extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -120,7 +125,8 @@ class Mock extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -129,7 +135,8 @@ class Mock extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -140,13 +147,14 @@ class Mock extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'http://localhost/'.$this->version.'/mock/tests/general/oauth2/user?token='.\urlencode($accessToken)); + $user = $this->request('GET', 'http://localhost/' . $this->version . '/mock/tests/general/oauth2/user?token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Notion.php b/src/Appwrite/Auth/OAuth2/Notion.php index 17c1dd7f18..c2f1ee98e4 100644 --- a/src/Appwrite/Auth/OAuth2/Notion.php +++ b/src/Appwrite/Auth/OAuth2/Notion.php @@ -44,31 +44,32 @@ class Notion extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'/oauth/authorize?'.\http_build_query([ + return $this->endpoint . '/oauth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', 'state' => \json_encode($this->state), - 'owner' => 'user', + 'owner' => 'user' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { - $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; + $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', $headers, \http_build_query([ 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callback, - 'code' => $code, + 'code' => $code ]) ), true); } @@ -77,15 +78,16 @@ class Notion extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { - $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; + $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', $headers, \http_build_query([ 'grant_type' => 'refresh_token', @@ -101,7 +103,8 @@ class Notion extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -112,7 +115,8 @@ class Notion extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -127,18 +131,20 @@ class Notion extends OAuth2 * * If present, the email is verified. This was verfied through a manual Notion sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -149,18 +155,19 @@ class Notion extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { $headers = [ - 'Notion-Version: '.$this->version, - 'Authorization: Bearer '.\urlencode($accessToken), + 'Notion-Version: ' . $this->version, + 'Authorization: Bearer ' . \urlencode($accessToken) ]; if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', $this->endpoint.'/users/me', $headers), true); + $this->user = \json_decode($this->request('GET', $this->endpoint . '/users/me', $headers), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Oidc.php b/src/Appwrite/Auth/OAuth2/Oidc.php index dfdf9aeff0..de2eab65c8 100644 --- a/src/Appwrite/Auth/OAuth2/Oidc.php +++ b/src/Appwrite/Auth/OAuth2/Oidc.php @@ -43,7 +43,7 @@ class Oidc extends OAuth2 */ public function getLoginURL(): string { - return $this->getAuthorizationEndpoint().'?'.\http_build_query([ + return $this->getAuthorizationEndpoint() . '?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), @@ -53,7 +53,8 @@ class Oidc extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -70,16 +71,17 @@ class Oidc extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } - return $this->tokens; } + /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -93,7 +95,7 @@ class Oidc extends OAuth2 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -105,7 +107,8 @@ class Oidc extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -120,7 +123,8 @@ class Oidc extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -137,7 +141,8 @@ class Oidc extends OAuth2 /** * Check if the User email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -148,7 +153,8 @@ class Oidc extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -162,14 +168,15 @@ class Oidc extends OAuth2 return ''; } - /** - * @param string $accessToken + /** + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; $user = $this->request('GET', $this->getUserinfoEndpoint(), $headers); $this->user = \json_decode($user, true); } @@ -189,7 +196,7 @@ class Oidc extends OAuth2 return $secret['clientSecret'] ?? ''; } - /** + /** * Extracts the well known endpoint from the JSON stored in appSecret. * * @return string @@ -197,14 +204,13 @@ class Oidc extends OAuth2 protected function getWellKnownEndpoint(): string { $secret = $this->getAppSecret(); - return $secret['wellKnownEndpoint'] ?? ''; } /** - * Extracts the authorization endpoint from the JSON stored in appSecret. - * - * If one is not provided, it will be retrieved from the well-known configuration. + * Extracts the authorization endpoint from the JSON stored in appSecret. + * + * If one is not provided, it will be retrieved from the well-known configuration. * * @return string */ @@ -213,59 +219,56 @@ class Oidc extends OAuth2 $secret = $this->getAppSecret(); $endpoint = $secret['authorizationEndpoint'] ?? ''; - if (! empty($endpoint)) { + if (!empty($endpoint)) { return $endpoint; } $wellKnownConfiguration = $this->getWellKnownConfiguration(); - return $wellKnownConfiguration['authorization_endpoint'] ?? ''; } /** - * Extracts the token endpoint from the JSON stored in appSecret. - * - * If one is not provided, it will be retrieved from the well-known configuration. - * - * @return string - */ + * Extracts the token endpoint from the JSON stored in appSecret. + * + * If one is not provided, it will be retrieved from the well-known configuration. + * + * @return string + */ protected function getTokenEndpoint(): string { $secret = $this->getAppSecret(); $endpoint = $secret['tokenEndpoint'] ?? ''; - if (! empty($endpoint)) { + if (!empty($endpoint)) { return $endpoint; } $wellKnownConfiguration = $this->getWellKnownConfiguration(); - return $wellKnownConfiguration['token_endpoint'] ?? ''; } /** - * Extracts the userinfo endpoint from the JSON stored in appSecret. - * - * If one is not provided, it will be retrieved from the well-known configuration. - * - * @return string - */ + * Extracts the userinfo endpoint from the JSON stored in appSecret. + * + * If one is not provided, it will be retrieved from the well-known configuration. + * + * @return string + */ protected function getUserinfoEndpoint(): string { $secret = $this->getAppSecret(); $endpoint = $secret['userinfoEndpoint'] ?? ''; - if (! empty($endpoint)) { + if (!empty($endpoint)) { return $endpoint; } $wellKnownConfiguration = $this->getWellKnownConfiguration(); - return $wellKnownConfiguration['userinfo_endpoint'] ?? ''; } - /** - * Get the well-known configuration using the well known endpoint - */ + /** + * Get the well-known configuration using the well known endpoint + */ protected function getWellKnownConfiguration(): array { if (empty($this->wellKnownConfiguration)) { @@ -288,7 +291,6 @@ class Oidc extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } - return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Okta.php b/src/Appwrite/Auth/OAuth2/Okta.php index 367c64e764..610d9847f2 100644 --- a/src/Appwrite/Auth/OAuth2/Okta.php +++ b/src/Appwrite/Auth/OAuth2/Okta.php @@ -16,7 +16,7 @@ class Okta extends OAuth2 'openid', 'profile', 'email', - 'offline_access', + 'offline_access' ]; /** @@ -42,17 +42,18 @@ class Okta extends OAuth2 */ public function getLoginURL(): string { - return 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/authorize?'.\http_build_query([ + return 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state), 'scope' => \implode(' ', $this->getScopes()), - 'response_type' => 'code', + 'response_type' => 'code' ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -61,7 +62,7 @@ class Okta extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/token', + 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/token', $headers, \http_build_query([ 'code' => $code, @@ -69,7 +70,7 @@ class Okta extends OAuth2 'client_secret' => $this->getClientSecret(), 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -77,8 +78,10 @@ class Okta extends OAuth2 return $this->tokens; } + /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -86,13 +89,13 @@ class Okta extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/token', + 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/token', $headers, \http_build_query([ 'refresh_token' => $refreshToken, 'client_id' => $this->appID, 'client_secret' => $this->getClientSecret(), - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -104,7 +107,8 @@ class Okta extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -115,7 +119,8 @@ class Okta extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -130,7 +135,8 @@ class Okta extends OAuth2 * * @link https://developer.okta.com/docs/reference/api/oidc/#userinfo * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -145,7 +151,8 @@ class Okta extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -156,14 +163,15 @@ class Okta extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; - $user = $this->request('GET', 'https://'.$this->getOktaDomain().'/oauth2/'.$this->getAuthorizationServerId().'/v1/userinfo', $headers); + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; + $user = $this->request('GET', 'https://' . $this->getOktaDomain() . '/oauth2/' . $this->getAuthorizationServerId() . '/v1/userinfo', $headers); $this->user = \json_decode($user, true); } @@ -218,7 +226,6 @@ class Okta extends OAuth2 } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } - return $secret; } } diff --git a/src/Appwrite/Auth/OAuth2/Paypal.php b/src/Appwrite/Auth/OAuth2/Paypal.php index e55ed05ac4..5d5bd0a06f 100644 --- a/src/Appwrite/Auth/OAuth2/Paypal.php +++ b/src/Appwrite/Auth/OAuth2/Paypal.php @@ -46,7 +46,7 @@ class Paypal extends OAuth2 protected array $scopes = [ 'openid', 'profile', - 'email', + 'email' ]; /** @@ -62,14 +62,14 @@ class Paypal extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint[$this->environment].'connect/?'. + $url = $this->endpoint[$this->environment] . 'connect/?' . \http_build_query([ 'flowEntry' => 'static', 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), // paypal is not accepting localhost string into return uri - 'redirect_uri' => \str_replace('localhost', '127.0.0.1', $this->callback), + 'redirect_uri' => \str_replace("localhost", "127.0.0.1", $this->callback), 'state' => \json_encode($this->state), ]); @@ -77,7 +77,8 @@ class Paypal extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -85,8 +86,8 @@ class Paypal extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->resourceEndpoint[$this->environment].'oauth2/token', - ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], + $this->resourceEndpoint[$this->environment] . 'oauth2/token', + ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], \http_build_query([ 'code' => $code, 'grant_type' => 'authorization_code', @@ -98,15 +99,16 @@ class Paypal extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->resourceEndpoint[$this->environment].'oauth2/token', - ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], + $this->resourceEndpoint[$this->environment] . 'oauth2/token', + ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], \http_build_query([ 'refresh_token' => $refreshToken, 'grant_type' => 'refresh_token', @@ -121,7 +123,8 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -132,7 +135,8 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -144,7 +148,7 @@ class Paypal extends OAuth2 return $email['primary'] === true; }); - if (! empty($email)) { + if (!empty($email)) { return $email[0]['value']; } } @@ -157,7 +161,8 @@ class Paypal extends OAuth2 * * @link https://developer.paypal.com/docs/api/identity/v1/#userinfo_get * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -172,7 +177,8 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -183,19 +189,20 @@ class Paypal extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { $header = [ 'Content-Type: application/json', - 'Authorization: Bearer '.\urlencode($accessToken), + 'Authorization: Bearer ' . \urlencode($accessToken), ]; if (empty($this->user)) { $user = $this->request( 'GET', - $this->resourceEndpoint[$this->environment].'identity/oauth2/userinfo?schema=paypalv1.1', + $this->resourceEndpoint[$this->environment] . 'identity/oauth2/userinfo?schema=paypalv1.1', $header ); $this->user = \json_decode($user, true); diff --git a/src/Appwrite/Auth/OAuth2/PaypalSandbox.php b/src/Appwrite/Auth/OAuth2/PaypalSandbox.php index e5ab612c0d..0f56a09c21 100644 --- a/src/Appwrite/Auth/OAuth2/PaypalSandbox.php +++ b/src/Appwrite/Auth/OAuth2/PaypalSandbox.php @@ -2,6 +2,8 @@ namespace Appwrite\Auth\OAuth2; +use Appwrite\Auth\OAuth2\Paypal; + class PaypalSandbox extends Paypal { protected string $environment = 'sandbox'; diff --git a/src/Appwrite/Auth/OAuth2/Podio.php b/src/Appwrite/Auth/OAuth2/Podio.php index f3ba81968e..e4194238d1 100644 --- a/src/Appwrite/Auth/OAuth2/Podio.php +++ b/src/Appwrite/Auth/OAuth2/Podio.php @@ -51,18 +51,19 @@ class Podio extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint.'/authorize?'. + $url = $this->endpoint . '/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'state' => \json_encode($this->state), - 'redirect_uri' => $this->callback, + 'redirect_uri' => $this->callback ]); return $url; } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -70,14 +71,14 @@ class Podio extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->apiEndpoint.'/oauth/token', + $this->apiEndpoint . '/oauth/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, 'redirect_uri' => $this->callback, 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, + 'client_secret' => $this->appSecret ]) ), true); } @@ -86,14 +87,15 @@ class Podio extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->apiEndpoint.'/oauth/token', + $this->apiEndpoint . '/oauth/token', ['Content-Type: application/x-www-form-urlencoded'], \http_build_query([ 'grant_type' => 'refresh_token', @@ -111,7 +113,8 @@ class Podio extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -122,7 +125,8 @@ class Podio extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -135,7 +139,8 @@ class Podio extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -143,7 +148,7 @@ class Podio extends OAuth2 $user = $this->getUser($accessToken); $mails = $user['mails']; - $mainMailIndex = \array_search($user['mail'], \array_map(fn ($m) => $m['mail'], $mails)); + $mainMailIndex = \array_search($user['mail'], \array_map(fn($m) => $m['mail'], $mails)); $mainMain = $mails[$mainMailIndex]; if ($mainMain['verified'] ?? false) { @@ -154,7 +159,8 @@ class Podio extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -165,7 +171,8 @@ class Podio extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array @@ -173,14 +180,14 @@ class Podio extends OAuth2 if (empty($this->user)) { $user = \json_decode($this->request( 'GET', - $this->apiEndpoint.'/user', - ['Authorization: Bearer '.\urlencode($accessToken)] + $this->apiEndpoint . '/user', + ['Authorization: Bearer ' . \urlencode($accessToken)] ), true); $profile = \json_decode($this->request( 'GET', - $this->apiEndpoint.'/user/profile', - ['Authorization: Bearer '.\urlencode($accessToken)] + $this->apiEndpoint . '/user/profile', + ['Authorization: Bearer ' . \urlencode($accessToken)] ), true); $this->user = $user; diff --git a/src/Appwrite/Auth/OAuth2/Salesforce.php b/src/Appwrite/Auth/OAuth2/Salesforce.php index 5fede655df..564fc51139 100644 --- a/src/Appwrite/Auth/OAuth2/Salesforce.php +++ b/src/Appwrite/Auth/OAuth2/Salesforce.php @@ -25,7 +25,7 @@ class Salesforce extends OAuth2 * @var array */ protected array $scopes = [ - 'openid', + "openid" ]; /** @@ -37,7 +37,8 @@ class Salesforce extends OAuth2 } /** - * @param string $state + * @param string $state + * * @return array */ public function parseState(string $state) @@ -45,29 +46,31 @@ class Salesforce extends OAuth2 return \json_decode(\html_entity_decode($state), true); } + /** * @return string */ public function getLoginURL(): string { - return 'https://login.salesforce.com/services/oauth2/authorize?'.\http_build_query([ + return 'https://login.salesforce.com/services/oauth2/authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { $headers = [ - 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), + 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -77,7 +80,7 @@ class Salesforce extends OAuth2 \http_build_query([ 'code' => $code, 'redirect_uri' => $this->callback, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -86,13 +89,14 @@ class Salesforce extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $headers = [ - 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), + 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -101,7 +105,7 @@ class Salesforce extends OAuth2 $headers, \http_build_query([ 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -113,7 +117,8 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -124,7 +129,8 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -139,7 +145,8 @@ class Salesforce extends OAuth2 * * @link https://help.salesforce.com/s/articleView?id=sf.remoteaccess_using_userinfo_endpoint.htm&type=5 * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -154,7 +161,8 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -165,16 +173,16 @@ class Salesforce extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://login.salesforce.com/services/oauth2/userinfo?access_token='.\urlencode($accessToken)); + $user = $this->request('GET', 'https://login.salesforce.com/services/oauth2/userinfo?access_token=' . \urlencode($accessToken)); $this->user = \json_decode($user, true); } - return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Slack.php b/src/Appwrite/Auth/OAuth2/Slack.php index ee6d43c0cc..8898f4d1f7 100644 --- a/src/Appwrite/Auth/OAuth2/Slack.php +++ b/src/Appwrite/Auth/OAuth2/Slack.php @@ -23,7 +23,7 @@ class Slack extends OAuth2 'identity.avatar', 'identity.basic', 'identity.email', - 'identity.team', + 'identity.team' ]; /** @@ -40,16 +40,17 @@ class Slack extends OAuth2 public function getLoginURL(): string { // https://api.slack.com/docs/oauth#step_1_-_sending_users_to_authorize_and_or_install - return 'https://slack.com/oauth/authorize?'.\http_build_query([ + return 'https://slack.com/oauth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -58,11 +59,11 @@ class Slack extends OAuth2 // https://api.slack.com/docs/oauth#step_3_-_exchanging_a_verification_code_for_an_access_token $this->tokens = \json_decode($this->request( 'GET', - 'https://slack.com/api/oauth.access?'.\http_build_query([ + 'https://slack.com/api/oauth.access?' . \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'code' => $code, - 'redirect_uri' => $this->callback, + 'redirect_uri' => $this->callback ]) ), true); } @@ -71,18 +72,19 @@ class Slack extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'GET', - 'https://slack.com/api/oauth.access?'.\http_build_query([ + 'https://slack.com/api/oauth.access?' . \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -94,7 +96,8 @@ class Slack extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -105,7 +108,8 @@ class Slack extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -122,18 +126,20 @@ class Slack extends OAuth2 * * @link https://slack.com/help/articles/207262907-Change-your-email-address * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -146,7 +152,8 @@ class Slack extends OAuth2 /** * @link https://api.slack.com/methods/users.identity * - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array @@ -154,7 +161,7 @@ class Slack extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - 'https://slack.com/api/users.identity?token='.\urlencode($accessToken) + 'https://slack.com/api/users.identity?token=' . \urlencode($accessToken) ); $this->user = \json_decode($user, true); diff --git a/src/Appwrite/Auth/OAuth2/Spotify.php b/src/Appwrite/Auth/OAuth2/Spotify.php index a8d5c531ab..d8e23cf0f0 100644 --- a/src/Appwrite/Auth/OAuth2/Spotify.php +++ b/src/Appwrite/Auth/OAuth2/Spotify.php @@ -49,32 +49,33 @@ class Spotify extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'authorize?'. + return $this->endpoint . 'authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { - $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; + $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'api/token', + $this->endpoint . 'api/token', $headers, \http_build_query([ - 'code' => $code, - 'grant_type' => 'authorization_code', - 'redirect_uri' => $this->callback, + "code" => $code, + "grant_type" => "authorization_code", + "redirect_uri" => $this->callback ]) ), true); } @@ -83,19 +84,20 @@ class Spotify extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { - $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)]; + $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'api/token', + $this->endpoint . 'api/token', $headers, \http_build_query([ - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + "refresh_token" => $refreshToken, + "grant_type" => "refresh_token", ]) ), true); @@ -107,7 +109,8 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -118,7 +121,8 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -135,7 +139,8 @@ class Spotify extends OAuth2 * * @link https://developer.spotify.com/documentation/web-api/reference/#/operations/get-current-users-profile * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -144,7 +149,8 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -155,7 +161,8 @@ class Spotify extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) @@ -163,8 +170,8 @@ class Spotify extends OAuth2 if (empty($this->user)) { $this->user = \json_decode($this->request( 'GET', - $this->resourceEndpoint.'me', - ['Authorization: Bearer '.\urlencode($accessToken)] + $this->resourceEndpoint . 'me', + ['Authorization: Bearer ' . \urlencode($accessToken)] ), true); } diff --git a/src/Appwrite/Auth/OAuth2/Stripe.php b/src/Appwrite/Auth/OAuth2/Stripe.php index 42260cad1e..5a959dbfcb 100644 --- a/src/Appwrite/Auth/OAuth2/Stripe.php +++ b/src/Appwrite/Auth/OAuth2/Stripe.php @@ -3,6 +3,7 @@ namespace Appwrite\Auth\OAuth2; use Appwrite\Auth\OAuth2; +use Utopia\Exception; class Stripe extends OAuth2 { @@ -49,17 +50,18 @@ class Stripe extends OAuth2 */ public function getLoginURL(): string { - return 'https://connect.stripe.com/oauth/authorize?'.\http_build_query([ + return 'https://connect.stripe.com/oauth/authorize?' . \http_build_query([ 'response_type' => 'code', // The only option at the moment is "code." 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -71,7 +73,7 @@ class Stripe extends OAuth2 [], \http_build_query([ 'grant_type' => $this->grantType['authorize'], - 'code' => $code, + 'code' => $code ]) ), true); @@ -82,7 +84,8 @@ class Stripe extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -102,12 +105,12 @@ class Stripe extends OAuth2 } $this->stripeAccountId = $this->tokens['stripe_user_id']; - return $this->tokens; } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -118,7 +121,8 @@ class Stripe extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -137,18 +141,20 @@ class Stripe extends OAuth2 * * If present, the email is verified. This was verfied through a manual Stripe sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -159,17 +165,18 @@ class Stripe extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) { - if (empty($this->user) && ! empty($this->stripeAccountId)) { + if (empty($this->user) && !empty($this->stripeAccountId)) { $this->user = \json_decode( $this->request( 'GET', - 'https://api.stripe.com/v1/accounts/'.$this->stripeAccountId, - ['Authorization: Bearer '.\urlencode($accessToken)] + 'https://api.stripe.com/v1/accounts/' . $this->stripeAccountId, + ['Authorization: Bearer ' . \urlencode($accessToken)] ), true ); diff --git a/src/Appwrite/Auth/OAuth2/Tradeshift.php b/src/Appwrite/Auth/OAuth2/Tradeshift.php index 350c152e4c..8d0bfa8784 100644 --- a/src/Appwrite/Auth/OAuth2/Tradeshift.php +++ b/src/Appwrite/Auth/OAuth2/Tradeshift.php @@ -10,7 +10,6 @@ use Appwrite\Auth\OAuth2; class Tradeshift extends OAuth2 { public const TRADESHIFT_SANDBOX_API_DOMAIN = 'api-sandbox.tradeshift.com'; - public const TRADESHIFT_API_DOMAIN = 'api.tradeshift.com'; private array $apiDomain = [ @@ -19,13 +18,13 @@ class Tradeshift extends OAuth2 ]; private array $endpoint = [ - 'sandbox' => 'https://'.self::TRADESHIFT_SANDBOX_API_DOMAIN.'/tradeshift/', - 'live' => 'https://'.self::TRADESHIFT_API_DOMAIN.'/tradeshift/', + 'sandbox' => 'https://' . self::TRADESHIFT_SANDBOX_API_DOMAIN . '/tradeshift/', + 'live' => 'https://' . self::TRADESHIFT_API_DOMAIN . '/tradeshift/', ]; private array $resourceEndpoint = [ - 'sandbox' => 'https://'.self::TRADESHIFT_SANDBOX_API_DOMAIN.'/tradeshift/rest/external/', - 'live' => 'https://'.self::TRADESHIFT_API_DOMAIN.'/tradeshift/rest/external/', + 'sandbox' => 'https://' . self::TRADESHIFT_SANDBOX_API_DOMAIN . '/tradeshift/rest/external/', + 'live' => 'https://' . self::TRADESHIFT_API_DOMAIN . '/tradeshift/rest/external/', ]; protected string $environment = 'live'; @@ -65,17 +64,18 @@ class Tradeshift extends OAuth2 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), - 'redirect_uri' => \str_replace('localhost', '127.0.0.1', $this->callback), + 'redirect_uri' => \str_replace("localhost", "127.0.0.1", $this->callback), 'state' => \json_encode($this->state), ]); - $url = $this->endpoint[$this->environment].'auth/login?'.$httpQuery; + $url = $this->endpoint[$this->environment] . 'auth/login?' . $httpQuery; return $url; } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -83,8 +83,8 @@ class Tradeshift extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint[$this->environment].'auth/token', - ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], + $this->endpoint[$this->environment] . 'auth/token', + ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], \http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, @@ -96,15 +96,16 @@ class Tradeshift extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint[$this->environment].'auth/token', - ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret)], + $this->endpoint[$this->environment] . 'auth/token', + ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)], \http_build_query([ 'grant_type' => 'refresh_token', 'refresh_token' => $refreshToken, @@ -119,7 +120,8 @@ class Tradeshift extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -130,7 +132,8 @@ class Tradeshift extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -145,18 +148,20 @@ class Tradeshift extends OAuth2 * * If present, the email is verified. This was verfied through a manual Tradeshift sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUser($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -166,11 +171,12 @@ class Tradeshift extends OAuth2 $firstName = $user['FirstName'] ?? ''; $lastName = $user['LastName'] ?? ''; - return $firstName.' '.$lastName; + return $firstName . ' ' . $lastName; } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array @@ -178,14 +184,14 @@ class Tradeshift extends OAuth2 $header = [ 'Content-Type: application/json', 'Accept: application/json', - 'Host: '.urlencode($this->apiDomain[$this->environment]), - 'Authorization: Bearer '.$accessToken, + 'Host: ' . urlencode($this->apiDomain[$this->environment]), + 'Authorization: Bearer ' . $accessToken, ]; if (empty($this->user)) { $response = $this->request( 'GET', - $this->resourceEndpoint[$this->environment].'account/info/user', + $this->resourceEndpoint[$this->environment] . 'account/info/user', $header ); $this->user = \json_decode($response, true); diff --git a/src/Appwrite/Auth/OAuth2/TradeshiftBox.php b/src/Appwrite/Auth/OAuth2/TradeshiftBox.php index d960acf2d3..27a4c0a456 100644 --- a/src/Appwrite/Auth/OAuth2/TradeshiftBox.php +++ b/src/Appwrite/Auth/OAuth2/TradeshiftBox.php @@ -2,6 +2,8 @@ namespace Appwrite\Auth\OAuth2; +use Appwrite\Auth\OAuth2\Tradeshift; + class TradeshiftBox extends Tradeshift { protected string $environment = 'sandbox'; diff --git a/src/Appwrite/Auth/OAuth2/Twitch.php b/src/Appwrite/Auth/OAuth2/Twitch.php index dad2efe800..ed73054c31 100644 --- a/src/Appwrite/Auth/OAuth2/Twitch.php +++ b/src/Appwrite/Auth/OAuth2/Twitch.php @@ -49,19 +49,20 @@ class Twitch extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'authorize?'. + return $this->endpoint . 'authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, 'force_verify' => true, - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -69,12 +70,12 @@ class Twitch extends OAuth2 if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'token?'.\http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'code' => $code, - 'grant_type' => 'authorization_code', - 'redirect_uri' => $this->callback, + $this->endpoint . 'token?' . \http_build_query([ + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "code" => $code, + "grant_type" => "authorization_code", + "redirect_uri" => $this->callback ]) ), true); } @@ -83,18 +84,19 @@ class Twitch extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'token?'.\http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + $this->endpoint . 'token?' . \http_build_query([ + "client_id" => $this->appID, + "client_secret" => $this->appSecret, + "refresh_token" => $refreshToken, + "grant_type" => "refresh_token", ]) ), true); @@ -106,7 +108,8 @@ class Twitch extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -117,7 +120,8 @@ class Twitch extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -134,18 +138,20 @@ class Twitch extends OAuth2 * * @link https://dev.twitch.tv/docs/api/reference#get-users * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -156,7 +162,8 @@ class Twitch extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) @@ -166,8 +173,8 @@ class Twitch extends OAuth2 'GET', $this->resourceEndpoint, [ - 'Authorization: Bearer '.\urlencode($accessToken), - 'Client-Id: '.\urlencode($this->appID), + 'Authorization: Bearer ' . \urlencode($accessToken), + 'Client-Id: ' . \urlencode($this->appID) ] ), true); diff --git a/src/Appwrite/Auth/OAuth2/WordPress.php b/src/Appwrite/Auth/OAuth2/WordPress.php index 084b890a5d..1bd55916fc 100644 --- a/src/Appwrite/Auth/OAuth2/WordPress.php +++ b/src/Appwrite/Auth/OAuth2/WordPress.php @@ -39,17 +39,18 @@ class WordPress extends OAuth2 */ public function getLoginURL(): string { - return 'https://public-api.wordpress.com/oauth2/authorize?'.\http_build_query([ + return 'https://public-api.wordpress.com/oauth2/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', 'scope' => $this->getScopes(), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -64,7 +65,7 @@ class WordPress extends OAuth2 'redirect_uri' => $this->callback, 'client_secret' => $this->appSecret, 'grant_type' => 'authorization_code', - 'code' => $code, + 'code' => $code ]) ), true); } @@ -73,7 +74,8 @@ class WordPress extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -86,7 +88,7 @@ class WordPress extends OAuth2 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, + 'refresh_token' => $refreshToken ]) ), true); @@ -98,7 +100,8 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -109,7 +112,8 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -128,7 +132,8 @@ class WordPress extends OAuth2 * * @link https://developer.wordpress.com/docs/api/1.1/get/me/ * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -143,7 +148,8 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -154,13 +160,14 @@ class WordPress extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) { if (empty($this->user)) { - $this->user = \json_decode($this->request('GET', 'https://public-api.wordpress.com/rest/v1/me', ['Authorization: Bearer '.$accessToken]), true); + $this->user = \json_decode($this->request('GET', 'https://public-api.wordpress.com/rest/v1/me', ['Authorization: Bearer ' . $accessToken]), true); } return $this->user; diff --git a/src/Appwrite/Auth/OAuth2/Yahoo.php b/src/Appwrite/Auth/OAuth2/Yahoo.php index 82496d666c..c70a2fb6c9 100644 --- a/src/Appwrite/Auth/OAuth2/Yahoo.php +++ b/src/Appwrite/Auth/OAuth2/Yahoo.php @@ -45,8 +45,10 @@ class Yahoo extends OAuth2 return 'yahoo'; } + /** * @param $state + * * @return array */ public function parseState(string $state) @@ -59,36 +61,37 @@ class Yahoo extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'request_auth?'. + return $this->endpoint . 'request_auth?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { $headers = [ - 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), + 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'get_token', + $this->endpoint . 'get_token', $headers, \http_build_query([ - 'code' => $code, - 'grant_type' => 'authorization_code', - 'redirect_uri' => $this->callback, + "code" => $code, + "grant_type" => "authorization_code", + "redirect_uri" => $this->callback ]) ), true); } @@ -97,23 +100,24 @@ class Yahoo extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $headers = [ - 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), + 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'get_token', + $this->endpoint . 'get_token', $headers, \http_build_query([ - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + "refresh_token" => $refreshToken, + "grant_type" => "refresh_token", ]) ), true); @@ -125,7 +129,8 @@ class Yahoo extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -136,7 +141,8 @@ class Yahoo extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -151,18 +157,20 @@ class Yahoo extends OAuth2 * * If present, the email is verified. This was verfied through a manual Yahoo sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -173,7 +181,8 @@ class Yahoo extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) @@ -182,7 +191,7 @@ class Yahoo extends OAuth2 $this->user = \json_decode($this->request( 'GET', $this->resourceEndpoint, - ['Authorization: Bearer '.\urlencode($accessToken)] + ['Authorization: Bearer ' . \urlencode($accessToken)] ), true); } diff --git a/src/Appwrite/Auth/OAuth2/Yammer.php b/src/Appwrite/Auth/OAuth2/Yammer.php index c6d1ba2837..9e1827bc58 100644 --- a/src/Appwrite/Auth/OAuth2/Yammer.php +++ b/src/Appwrite/Auth/OAuth2/Yammer.php @@ -37,17 +37,18 @@ class Yammer extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'oauth2/authorize?'. + return $this->endpoint . 'oauth2/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'response_type' => 'code', 'redirect_uri' => $this->callback, - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array @@ -56,13 +57,13 @@ class Yammer extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'access_token?', + $this->endpoint . 'access_token?', $headers, \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'code' => $code, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -71,7 +72,8 @@ class Yammer extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array @@ -79,13 +81,13 @@ class Yammer extends OAuth2 $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'access_token?', + $this->endpoint . 'access_token?', $headers, \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', + 'grant_type' => 'refresh_token' ]) ), true); @@ -97,7 +99,8 @@ class Yammer extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -108,7 +111,8 @@ class Yammer extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -123,18 +127,20 @@ class Yammer extends OAuth2 * * If present, the email is verified. This was verfied through a manual Yammer sign up process * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool { $email = $this->getUserEmail($accessToken); - return ! empty($email); + return !empty($email); } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -145,13 +151,14 @@ class Yammer extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $headers = ['Authorization: Bearer '.\urlencode($accessToken)]; + $headers = ['Authorization: Bearer ' . \urlencode($accessToken)]; $user = $this->request('GET', 'https://www.yammer.com/api/v1/users/current.json', $headers); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Yandex.php b/src/Appwrite/Auth/OAuth2/Yandex.php index 13e1fb4dfc..a6a2e2e550 100644 --- a/src/Appwrite/Auth/OAuth2/Yandex.php +++ b/src/Appwrite/Auth/OAuth2/Yandex.php @@ -8,6 +8,7 @@ use Appwrite\Auth\OAuth2; // https://tech.yandex.com/passport/doc/dg/reference/request-docpage/ // https://tech.yandex.com/oauth/doc/dg/reference/web-client-docpage/ + class Yandex extends OAuth2 { /** @@ -34,7 +35,8 @@ class Yandex extends OAuth2 } /** - * @param string $state + * @param string $state + * * @return array */ public function parseState(string $state) @@ -42,28 +44,30 @@ class Yandex extends OAuth2 return \json_decode(\html_entity_decode($state), true); } + /** * @return string */ public function getLoginURL(): string { - return 'https://oauth.yandex.com/authorize?'.\http_build_query([ + return 'https://oauth.yandex.com/authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \json_encode($this->state) ]); } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { $headers = [ - 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), + 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -72,7 +76,7 @@ class Yandex extends OAuth2 $headers, \http_build_query([ 'code' => $code, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); } @@ -81,13 +85,14 @@ class Yandex extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { $headers = [ - 'Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), + 'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded', ]; $this->tokens = \json_decode($this->request( @@ -96,7 +101,7 @@ class Yandex extends OAuth2 $headers, \http_build_query([ 'refresh_token' => $refreshToken, - 'grant_type' => 'authorization_code', + 'grant_type' => 'authorization_code' ]) ), true); @@ -108,7 +113,8 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -119,7 +125,8 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -132,7 +139,8 @@ class Yandex extends OAuth2 /** * Check if the OAuth email is verified * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -141,7 +149,8 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string @@ -152,19 +161,19 @@ class Yandex extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken): array { if (empty($this->user)) { - $user = $this->request('GET', 'https://login.yandex.ru/info?'.\http_build_query([ + $user = $this->request('GET', 'https://login.yandex.ru/info?' . \http_build_query([ 'format' => 'json', - 'oauth_token' => $accessToken, + 'oauth_token' => $accessToken ])); $this->user = \json_decode($user, true); } - return $this->user; } } diff --git a/src/Appwrite/Auth/OAuth2/Zoom.php b/src/Appwrite/Auth/OAuth2/Zoom.php index 01ade69a48..9dad22212a 100644 --- a/src/Appwrite/Auth/OAuth2/Zoom.php +++ b/src/Appwrite/Auth/OAuth2/Zoom.php @@ -30,7 +30,7 @@ class Zoom extends OAuth2 * @var array */ protected array $scopes = [ - 'user_info:read', + 'user_info:read' ]; /** @@ -46,7 +46,7 @@ class Zoom extends OAuth2 */ public function getLoginURL(): string { - return $this->endpoint.'/oauth/authorize?'.\http_build_query([ + return $this->endpoint . '/oauth/authorize?' . \http_build_query([ 'client_id' => $this->appID, 'redirect_uri' => $this->callback, 'response_type' => 'code', @@ -56,21 +56,22 @@ class Zoom extends OAuth2 } /** - * @param string $code + * @param string $code + * * @return array */ protected function getTokens(string $code): array { if (empty($this->tokens)) { - $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; + $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', $headers, \http_build_query([ 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callback, - 'code' => $code, + 'code' => $code ]) ), true); } @@ -79,15 +80,16 @@ class Zoom extends OAuth2 } /** - * @param string $refreshToken + * @param string $refreshToken + * * @return array */ public function refreshTokens(string $refreshToken): array { - $headers = ['Authorization: Basic '.\base64_encode($this->appID.':'.$this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; + $headers = ['Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret), 'Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( 'POST', - $this->endpoint.'/oauth/token', + $this->endpoint . '/oauth/token', $headers, \http_build_query([ 'grant_type' => 'refresh_token', @@ -103,7 +105,8 @@ class Zoom extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserID(string $accessToken): string @@ -114,7 +117,8 @@ class Zoom extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserEmail(string $accessToken): string @@ -129,7 +133,8 @@ class Zoom extends OAuth2 * * @link https://marketplace.zoom.us/docs/api-reference/zoom-api/methods/#operation/user * - * @param string $accessToken + * @param string $accessToken + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -144,24 +149,26 @@ class Zoom extends OAuth2 } /** - * @param string $accessToken + * @param string $accessToken + * * @return string */ public function getUserName(string $accessToken): string { $response = $this->getUser($accessToken); - return ($response['first_name'] ?? '').' '.($response['last_name'] ?? ''); + return ($response['first_name'] ?? '') . ' ' . ($response['last_name'] ?? ''); } /** - * @param string $accessToken + * @param string $accessToken + * * @return array */ protected function getUser(string $accessToken) { $headers = [ - 'Authorization: Bearer '.\urlencode($accessToken), + 'Authorization: Bearer ' . \urlencode($accessToken) ]; if (empty($this->user)) { diff --git a/src/Appwrite/Auth/Validator/Password.php b/src/Appwrite/Auth/Validator/Password.php index e997d03f81..93a9f74114 100644 --- a/src/Appwrite/Auth/Validator/Password.php +++ b/src/Appwrite/Auth/Validator/Password.php @@ -26,12 +26,13 @@ class Password extends Validator /** * Is valid. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($value): bool { - if (! \is_string($value)) { + if (!\is_string($value)) { return false; } diff --git a/src/Appwrite/Auth/Validator/PasswordDictionary.php b/src/Appwrite/Auth/Validator/PasswordDictionary.php index 27feeeca36..003d68bc73 100644 --- a/src/Appwrite/Auth/Validator/PasswordDictionary.php +++ b/src/Appwrite/Auth/Validator/PasswordDictionary.php @@ -10,7 +10,6 @@ namespace Appwrite\Auth\Validator; class PasswordDictionary extends Password { protected array $dictionary; - protected bool $enabled; public function __construct(array $dictionary, bool $enabled = false) @@ -34,19 +33,19 @@ class PasswordDictionary extends Password /** * Is valid. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($value): bool { - if (! parent::isValid($value)) { + if (!parent::isValid($value)) { return false; } if ($this->enabled && array_key_exists($value, $this->dictionary)) { return false; } - return true; } diff --git a/src/Appwrite/Auth/Validator/PasswordHistory.php b/src/Appwrite/Auth/Validator/PasswordHistory.php index d78abe6689..8cfabf4666 100644 --- a/src/Appwrite/Auth/Validator/PasswordHistory.php +++ b/src/Appwrite/Auth/Validator/PasswordHistory.php @@ -12,9 +12,7 @@ use Appwrite\Auth\Auth; class PasswordHistory extends Password { protected array $history; - protected string $algo; - protected array $algoOptions; public function __construct(array $history, string $algo, array $algoOptions = []) @@ -39,7 +37,8 @@ class PasswordHistory extends Password /** * Is valid. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($value): bool @@ -49,7 +48,6 @@ class PasswordHistory extends Password return false; } } - return true; } diff --git a/src/Appwrite/Auth/Validator/PersonalData.php b/src/Appwrite/Auth/Validator/PersonalData.php index 911d8f5515..6f8ed0a8c9 100644 --- a/src/Appwrite/Auth/Validator/PersonalData.php +++ b/src/Appwrite/Auth/Validator/PersonalData.php @@ -31,16 +31,17 @@ class PersonalData extends Password /** * Is valid. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($password): bool { - if (! parent::isValid($password)) { + if (!parent::isValid($password)) { return false; } - if (! $this->strict) { + if (!$this->strict) { $password = strtolower($password); $this->userId = strtolower($this->userId); $this->email = strtolower($this->email); diff --git a/src/Appwrite/Auth/Validator/Phone.php b/src/Appwrite/Auth/Validator/Phone.php index 49d78ac8c6..32c3ca3398 100644 --- a/src/Appwrite/Auth/Validator/Phone.php +++ b/src/Appwrite/Auth/Validator/Phone.php @@ -26,12 +26,13 @@ class Phone extends Validator /** * Is valid. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($value): bool { - return is_string($value) && (bool) \preg_match('/^\+[1-9]\d{1,14}$/', $value); + return is_string($value) && !!\preg_match('/^\+[1-9]\d{1,14}$/', $value); } /** diff --git a/src/Appwrite/Detector/Detector.php b/src/Appwrite/Detector/Detector.php index ed1be7325b..62f7a0a04b 100644 --- a/src/Appwrite/Detector/Detector.php +++ b/src/Appwrite/Detector/Detector.php @@ -17,7 +17,7 @@ class Detector protected $detctor; /** - * @param string $userAgent + * @param string $userAgent */ public function __construct(string $userAgent) { @@ -54,7 +54,7 @@ class Detector 'type' => 'desktop', 'short_name' => 'cli', 'name' => 'Appwrite CLI', - 'version' => $version, + 'version' => $version ]; } else { $client = $this->getDetector()->getClient(); @@ -89,7 +89,7 @@ class Detector */ protected function getDetector(): DeviceDetector { - if (! $this->detctor) { + if (!$this->detctor) { $this->detctor = new DeviceDetector($this->userAgent); $this->detctor->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) $this->detctor->parse(); @@ -103,7 +103,7 @@ class Detector * It is needed if we want bots to be processed as a simple clients. So we can detect if it is mobile client, * or desktop, or enything else. By default all this information is not retrieved for the bots. * - * @param bool $skip + * @param bool $skip */ public function skipBotDetection(bool $skip = true): void { diff --git a/src/Appwrite/Docker/Compose.php b/src/Appwrite/Docker/Compose.php index 0b4a8b16b9..64441805de 100644 --- a/src/Appwrite/Docker/Compose.php +++ b/src/Appwrite/Docker/Compose.php @@ -13,7 +13,7 @@ class Compose protected $compose = []; /** - * @var string + * @var string $data */ public function __construct(string $data) { @@ -48,7 +48,7 @@ class Compose */ public function getService(string $name): Service { - if (! isset($this->compose['services'][$name])) { + if (!isset($this->compose['services'][$name])) { throw new Exception('Service not found'); } diff --git a/src/Appwrite/Docker/Compose/Service.php b/src/Appwrite/Docker/Compose/Service.php index 32c12b82b1..a3f9c91253 100644 --- a/src/Appwrite/Docker/Compose/Service.php +++ b/src/Appwrite/Docker/Compose/Service.php @@ -12,7 +12,7 @@ class Service protected $service = []; /** - * @var string + * @var string $path */ public function __construct(array $service) { @@ -54,8 +54,7 @@ class Service public function getImageVersion(): string { $image = $this->getImage(); - - return substr($image, ((int) strpos($image, ':')) + 1); + return substr($image, ((int)strpos($image, ':')) + 1); } /** diff --git a/src/Appwrite/Docker/Env.php b/src/Appwrite/Docker/Env.php index 6351ce4f78..bce12a95e6 100644 --- a/src/Appwrite/Docker/Env.php +++ b/src/Appwrite/Docker/Env.php @@ -2,6 +2,8 @@ namespace Appwrite\Docker; +use Exception; + class Env { /** @@ -10,7 +12,7 @@ class Env protected $vars = []; /** - * @var string + * @var string $data */ public function __construct(string $data) { @@ -28,8 +30,9 @@ class Env } /** - * @param string $key - * @param mixed $value + * @param string $key + * @param mixed $value + * * @return $this */ public function setVar(string $key, $value): self @@ -40,7 +43,8 @@ class Env } /** - * @param string $key + * @param string $key + * * @return string */ public function getVar(string $key): string @@ -66,7 +70,7 @@ class Env $output = ''; foreach ($this->vars as $key => $value) { - $output .= $key.'='.$value."\n"; + $output .= $key . '=' . $value . "\n"; } return $output; diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index da396bba17..254f7c294a 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -7,11 +7,8 @@ use Resque; class Audit extends Event { protected string $resource = ''; - protected string $mode = ''; - protected string $userAgent = ''; - protected string $ip = ''; public function __construct() @@ -22,7 +19,7 @@ class Audit extends Event /** * Set resource for this audit event. * - * @param string $resource + * @param string $resource * @return self */ public function setResource(string $resource): self @@ -45,7 +42,7 @@ class Audit extends Event /** * Set mode for this audit event * - * @param string $mode + * @param string $mode * @return self */ public function setMode(string $mode): self @@ -68,7 +65,7 @@ class Audit extends Event /** * Set user agent for this audit event. * - * @param string $userAgent + * @param string $userAgent * @return self */ public function setUserAgent(string $userAgent): self @@ -91,7 +88,7 @@ class Audit extends Event /** * Set IP for this audit event. * - * @param string $ip + * @param string $ip * @return self */ public function setIP(string $ip): self @@ -115,7 +112,6 @@ class Audit extends Event * Executes the event and sends it to the audit worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index 92e4659dd7..4d4b338118 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -8,9 +8,7 @@ use Utopia\Database\Document; class Build extends Event { protected string $type = ''; - protected ?Document $resource = null; - protected ?Document $deployment = null; public function __construct() @@ -21,7 +19,7 @@ class Build extends Event /** * Sets resource document for the build event. * - * @param Document $resource + * @param Document $resource * @return self */ public function setResource(Document $resource): self @@ -44,7 +42,7 @@ class Build extends Event /** * Sets deployment for the build event. * - * @param Document $deployment + * @param Document $deployment * @return self */ public function setDeployment(Document $deployment): self @@ -67,7 +65,7 @@ class Build extends Event /** * Sets type for the build event. * - * @param string $type Can be `BUILD_TYPE_DEPLOYMENT` or `BUILD_TYPE_RETRY`. + * @param string $type Can be `BUILD_TYPE_DEPLOYMENT` or `BUILD_TYPE_RETRY`. * @return self */ public function setType(string $type): self @@ -91,7 +89,6 @@ class Build extends Event * Executes the function event and sends it to the functions worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -100,7 +97,7 @@ class Build extends Event 'project' => $this->project, 'resource' => $this->resource, 'deployment' => $this->deployment, - 'type' => $this->type, + 'type' => $this->type ]); } } diff --git a/src/Appwrite/Event/Certificate.php b/src/Appwrite/Event/Certificate.php index c39adbed8f..d3d9091804 100644 --- a/src/Appwrite/Event/Certificate.php +++ b/src/Appwrite/Event/Certificate.php @@ -8,7 +8,6 @@ use Utopia\Database\Document; class Certificate extends Event { protected bool $skipRenewCheck = false; - protected ?Document $domain = null; public function __construct() @@ -19,7 +18,7 @@ class Certificate extends Event /** * Set domain for this certificates event. * - * @param Document $domain + * @param Document $domain * @return self */ public function setDomain(Document $domain): self @@ -42,7 +41,7 @@ class Certificate extends Event /** * Set if the certificate needs to be validated. * - * @param bool $skipRenewCheck + * @param bool $skipRenewCheck * @return self */ public function setSkipRenewCheck(bool $skipRenewCheck): self @@ -66,7 +65,6 @@ class Certificate extends Event * Executes the event and sends it to the certificates worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -74,7 +72,7 @@ class Certificate extends Event return Resque::enqueue($this->queue, $this->class, [ 'project' => $this->project, 'domain' => $this->domain, - 'skipRenewCheck' => $this->skipRenewCheck, + 'skipRenewCheck' => $this->skipRenewCheck ]); } } diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index cc83263d71..1822f06c71 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -8,11 +8,8 @@ use Utopia\Database\Document; class Database extends Event { protected string $type = ''; - protected ?Document $database = null; - protected ?Document $collection = null; - protected ?Document $document = null; public function __construct() @@ -23,7 +20,7 @@ class Database extends Event /** * Sets the type for this database event (use the constants starting with DATABASE_TYPE_*). * - * @param string $type + * @param string $type * @return self */ public function setType(string $type): self @@ -35,7 +32,6 @@ class Database extends Event /** * Returns the set type for the database event. - * * @return string */ public function getType(): string @@ -46,20 +42,19 @@ class Database extends Event /** * Set the database for this event * - * @param Document $database + * @param Document $database * @return self */ public function setDatabase(Document $database): self { $this->database = $database; - return $this; } /** * Set the collection for this database event. * - * @param Document $collection + * @param Document $collection * @return self */ public function setCollection(Document $collection): self @@ -82,7 +77,7 @@ class Database extends Event /** * Set the document for this database event. * - * @param Document $document + * @param Document $document * @return self */ public function setDocument(Document $document): self @@ -94,7 +89,6 @@ class Database extends Event /** * Returns set document for this database event. - * * @return null|Document */ public function getDocument(): ?Document @@ -106,7 +100,6 @@ class Database extends Event * Executes the event and send it to the database worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -118,7 +111,7 @@ class Database extends Event 'collection' => $this->collection, 'document' => $this->document, 'database' => $this->database, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); } } diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index dee01ed6bf..d1519121a6 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -8,15 +8,12 @@ use Utopia\Database\Document; class Delete extends Event { protected string $type = ''; - protected ?Document $document = null; - protected ?string $resource = null; - protected ?string $datetime = null; - protected ?string $hourlyUsageRetentionDatetime = null; + public function __construct() { parent::__construct(Event::DELETE_QUEUE_NAME, Event::DELETE_CLASS_NAME); @@ -25,7 +22,7 @@ class Delete extends Event /** * Sets the type for the delete event (use the constants starting with DELETE_TYPE_*). * - * @param string $type + * @param string $type * @return self */ public function setType(string $type): self @@ -48,33 +45,31 @@ class Delete extends Event /** * set Datetime. * - * @param string $datetime + * @param string $datetime * @return self */ public function setDatetime(string $datetime): self { $this->datetime = $datetime; - return $this; } /** * Sets datetime for 1h interval. * - * @param string $datetime + * @param string $datetime * @return self */ public function setUsageRetentionHourlyDateTime(string $datetime): self { $this->hourlyUsageRetentionDatetime = $datetime; - return $this; } /** * Sets the document for the delete event. * - * @param Document $document + * @param Document $document * @return self */ public function setDocument(Document $document): self @@ -97,7 +92,7 @@ class Delete extends Event /** * Sets the resource for the delete event. * - * @param string $resource + * @param string $resource * @return self */ public function setResource(string $resource): self @@ -117,11 +112,11 @@ class Delete extends Event return $this->document; } + /** * Executes this event and sends it to the deletes worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 0000cc482d..23dde49637 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -9,70 +9,51 @@ use Utopia\Database\Document; class Event { public const DATABASE_QUEUE_NAME = 'v1-database'; - public const DATABASE_CLASS_NAME = 'DatabaseV1'; public const DELETE_QUEUE_NAME = 'v1-deletes'; - public const DELETE_CLASS_NAME = 'DeletesV1'; public const AUDITS_QUEUE_NAME = 'v1-audits'; - public const AUDITS_CLASS_NAME = 'AuditsV1'; public const MAILS_QUEUE_NAME = 'v1-mails'; - public const MAILS_CLASS_NAME = 'MailsV1'; public const FUNCTIONS_QUEUE_NAME = 'v1-functions'; - public const FUNCTIONS_CLASS_NAME = 'FunctionsV1'; public const USAGE_QUEUE_NAME = 'v1-usage'; - public const USAGE_CLASS_NAME = 'UsageV1'; public const WEBHOOK_QUEUE_NAME = 'v1-webhooks'; - public const WEBHOOK_CLASS_NAME = 'WebhooksV1'; public const CERTIFICATES_QUEUE_NAME = 'v1-certificates'; - public const CERTIFICATES_CLASS_NAME = 'CertificatesV1'; public const BUILDS_QUEUE_NAME = 'v1-builds'; - public const BUILDS_CLASS_NAME = 'BuildsV1'; public const MESSAGING_QUEUE_NAME = 'v1-messaging'; - public const MESSAGING_CLASS_NAME = 'MessagingV1'; public const MIGRATIONS_QUEUE_NAME = 'v1-migrations'; - public const MIGRATIONS_CLASS_NAME = 'MigrationsV1'; protected string $queue = ''; - protected string $class = ''; - protected string $event = ''; - protected array $params = []; - protected array $payload = []; - protected array $context = []; - protected ?Document $project = null; - protected ?Document $user = null; - protected bool $paused = false; /** - * @param string $queue - * @param string $class + * @param string $queue + * @param string $class * @return void */ public function __construct(string $queue, string $class) @@ -84,7 +65,7 @@ class Event /** * Set queue used for this event. * - * @param string $queue + * @param string $queue * @return Event */ public function setQueue(string $queue): self @@ -106,8 +87,7 @@ class Event /** * Set event name used for this event. - * - * @param string $event + * @param string $event * @return Event */ public function setEvent(string $event): self @@ -130,7 +110,7 @@ class Event /** * Set project for this event. * - * @param Document $project + * @param Document $project * @return self */ public function setProject(Document $project): self @@ -153,7 +133,7 @@ class Event /** * Set user for this event. * - * @param Document $user + * @param Document $user * @return self */ public function setUser(Document $user): self @@ -176,7 +156,7 @@ class Event /** * Set payload for this event. * - * @param array $payload + * @param array $payload * @return self */ public function setPayload(array $payload): self @@ -199,8 +179,8 @@ class Event /** * Set context for this event. * - * @param string $key - * @param Document $context + * @param string $key + * @param Document $context * @return self */ public function setContext(string $key, Document $context): self @@ -213,7 +193,8 @@ class Event /** * Get context for this event. * - * @param string $key + * @param string $key + * * @return null|Document */ public function getContext(string $key): ?Document @@ -223,8 +204,7 @@ class Event /** * Set class used for this event. - * - * @param string $class + * @param string $class * @return self */ public function setClass(string $class): self @@ -247,8 +227,8 @@ class Event /** * Set param of event. * - * @param string $key - * @param mixed $value + * @param string $key + * @param mixed $value * @return self */ public function setParam(string $key, mixed $value): self @@ -261,7 +241,7 @@ class Event /** * Get param of event. * - * @param string $key + * @param string $key * @return mixed */ public function getParam(string $key): mixed @@ -283,7 +263,6 @@ class Event * Execute Event. * * @return string|bool - * * @throws InvalidArgumentException */ public function trigger(): string|bool @@ -297,7 +276,7 @@ class Event 'user' => $this->user, 'payload' => $this->payload, 'context' => $this->context, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); } @@ -316,7 +295,7 @@ class Event /** * Parses event pattern and returns the parts in their respective section. * - * @param string $pattern + * @param string $pattern * @return array */ public static function parseEventPattern(string $pattern): array @@ -345,13 +324,13 @@ class Event } } - if ($hasSubResource && ! $hasSubSubResource) { + if ($hasSubResource && !$hasSubSubResource) { if ($count === 6) { $attribute = $parts[5]; } } - if (! $hasSubResource) { + if (!$hasSubResource) { if ($count === 4) { $attribute = $parts[3]; } @@ -363,7 +342,7 @@ class Event $subSubResource ??= false; $attribute ??= false; $action = match (true) { - ! $hasSubResource && $count > 2 => $parts[2], + !$hasSubResource && $count > 2 => $parts[2], $hasSubSubResource => $parts[6] ?? false, $hasSubResource && $count > 4 => $parts[4], default => false @@ -384,10 +363,9 @@ class Event /** * Generates all possible events from a pattern. * - * @param string $pattern - * @param array $params + * @param string $pattern + * @param array $params * @return array - * * @throws \InvalidArgumentException */ public static function generateEvents(string $pattern, array $params = []): array @@ -408,15 +386,15 @@ class Event $action = $parsed['action']; $attribute = $parsed['attribute']; - if ($resource && ! \in_array(\trim($resource, "\[\]"), $paramKeys)) { + if ($resource && !\in_array(\trim($resource, "\[\]"), $paramKeys)) { throw new InvalidArgumentException("{$resource} is missing from the params."); } - if ($subResource && ! \in_array(\trim($subResource, "\[\]"), $paramKeys)) { + if ($subResource && !\in_array(\trim($subResource, "\[\]"), $paramKeys)) { throw new InvalidArgumentException("{$subResource} is missing from the params."); } - if ($subSubResource && ! \in_array(\trim($subSubResource, "\[\]"), $paramKeys)) { + if ($subSubResource && !\in_array(\trim($subSubResource, "\[\]"), $paramKeys)) { throw new InvalidArgumentException("{$subSubResource} is missing from the params."); } @@ -470,9 +448,9 @@ class Event if ($subCurrent === $current || $subCurrent === $key) { continue; } - $filtered1 = \array_filter($paramKeys, fn (string $k) => $k === $subCurrent); + $filtered1 = \array_filter($paramKeys, fn(string $k) => $k === $subCurrent); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered1, '*', $eventPattern)); - $filtered2 = \array_filter($paramKeys, fn (string $k) => $k === $current); + $filtered2 = \array_filter($paramKeys, fn(string $k) => $k === $current); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered2, '*', \str_replace($filtered1, '*', $eventPattern))); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered2, '*', $eventPattern)); } @@ -480,7 +458,7 @@ class Event if ($current === $key) { continue; } - $filtered = \array_filter($paramKeys, fn (string $k) => $k === $current); + $filtered = \array_filter($paramKeys, fn(string $k) => $k === $current); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered, '*', $eventPattern)); } } diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index dea2381cda..d121b47a4a 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -9,13 +9,9 @@ use Utopia\Queue\Connection; class Func extends Event { protected string $jwt = ''; - protected string $type = ''; - protected string $data = ''; - protected ?Document $function = null; - protected ?Document $execution = null; public function __construct(protected Connection $connection) @@ -26,7 +22,7 @@ class Func extends Event /** * Sets function document for the function event. * - * @param Document $function + * @param Document $function * @return self */ public function setFunction(Document $function): self @@ -49,7 +45,7 @@ class Func extends Event /** * Sets execution for the function event. * - * @param Document $execution + * @param Document $execution * @return self */ public function setExecution(Document $execution): self @@ -72,7 +68,7 @@ class Func extends Event /** * Sets type for the function event. * - * @param string $type Can be `schedule`, `event` or `http`. + * @param string $type Can be `schedule`, `event` or `http`. * @return self */ public function setType(string $type): self @@ -95,7 +91,7 @@ class Func extends Event /** * Sets custom data for the function event. * - * @param string $data + * @param string $data * @return self */ public function setData(string $data): self @@ -118,7 +114,7 @@ class Func extends Event /** * Sets JWT for the function event. * - * @param string $jwt + * @param string $jwt * @return self */ public function setJWT(string $jwt): self @@ -142,7 +138,6 @@ class Func extends Event * Executes the function event and sends it to the functions worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -171,8 +166,10 @@ class Func extends Event /** * Generate a function event from a base event * - * @param Event $event + * @param Event $event + * * @return self + * */ public function from(Event $event): self { @@ -181,7 +178,6 @@ class Func extends Event $this->payload = $event->getPayload(); $this->event = $event->getEvent(); $this->params = $event->getParams(); - return $this; } } diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index 68a6cfe2a3..37b42704c5 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -3,19 +3,15 @@ namespace Appwrite\Event; use Resque; +use Utopia\Database\Document; class Mail extends Event { protected string $recipient = ''; - protected string $from = ''; - protected string $name = ''; - protected string $subject = ''; - protected string $body = ''; - protected array $smtp = []; public function __construct() @@ -26,7 +22,7 @@ class Mail extends Event /** * Sets subject for the mail event. * - * @param string $subject + * @param string $subject * @return self */ public function setSubject(string $subject): self @@ -49,7 +45,7 @@ class Mail extends Event /** * Sets recipient for the mail event. * - * @param string $recipient + * @param string $recipient * @return self */ public function setRecipient(string $recipient): self @@ -72,7 +68,7 @@ class Mail extends Event /** * Sets from for the mail event. * - * @param string $from + * @param string $from * @return self */ public function setFrom(string $from): self @@ -95,7 +91,7 @@ class Mail extends Event /** * Sets body for the mail event. * - * @param string $body + * @param string $body * @return self */ public function setBody(string $body): self @@ -118,7 +114,7 @@ class Mail extends Event /** * Sets name for the mail event. * - * @param string $name + * @param string $name * @return self */ public function setName(string $name): self @@ -141,13 +137,12 @@ class Mail extends Event /** * Set SMTP Host * - * @param string $host + * @param string $host * @return self */ public function setSmtpHost(string $host): self { $this->smtp['host'] = $host; - return $this; } @@ -160,59 +155,54 @@ class Mail extends Event public function setSmtpPort(int $port): self { $this->smtp['port'] = $port; - return $this; } /** * Set SMTP username * - * @param string $username + * @param string $username * @return self */ public function setSmtpUsername(string $username): self { $this->smtp['username']; - return $this; } /** * Set SMTP password * - * @param string $password + * @param string $password * @return self */ public function setSmtpPassword(string $password): self { $this->smtp['password']; - return $this; } /** * Set SMTP sender email * - * @param string $senderEmail + * @param string $senderEmail * @return self */ public function setSmtpSenderEmail(string $senderEmail): self { $this->smtp['senderEmail'] = $senderEmail; - return $this; } /** * Set SMTP reply to * - * @param string $replyTo + * @param string $replyTo * @return self */ public function setSmtpReplyTo(string $replyTo): self { $this->smtp['replyTo'] = $replyTo; - return $this; } @@ -229,7 +219,7 @@ class Mail extends Event /** * Get SMTP port * - * @return int + * @return integer */ public function getSmtpPort(): int { @@ -280,7 +270,6 @@ class Mail extends Event * Executes the event and sends it to the mails worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -292,7 +281,7 @@ class Mail extends Event 'subject' => $this->subject, 'body' => $this->body, 'smtp' => $this->smtp, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); } } diff --git a/src/Appwrite/Event/Migration.php b/src/Appwrite/Event/Migration.php index ebe15483d0..4d53f16796 100644 --- a/src/Appwrite/Event/Migration.php +++ b/src/Appwrite/Event/Migration.php @@ -10,7 +10,6 @@ use Utopia\Database\Document; class Migration extends Event { protected string $type = ''; - protected ?Document $migration = null; public function __construct() @@ -21,7 +20,7 @@ class Migration extends Event /** * Sets migration document for the migration event. * - * @param Document $migration + * @param Document $migration * @return self */ public function setMigration(Document $migration): self @@ -44,7 +43,8 @@ class Migration extends Event /** * Sets migration type for the migration event. * - * @param string $type + * @param string $type + * * @return self */ public function setType(string $type): self @@ -68,7 +68,6 @@ class Migration extends Event * Executes the migration event and sends it to the migrations worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -76,16 +75,15 @@ class Migration extends Event return Resque::enqueue($this->queue, $this->class, [ 'project' => $this->project, 'user' => $this->user, - 'migration' => $this->migration, + 'migration' => $this->migration ]); } /** * Schedules the migration event and schedules it in the migrations worker queue. * - * @param \DateTime|int $at + * @param \DateTime|int $at * @return void - * * @throws \Resque_Exception * @throws \ResqueScheduler_InvalidTimestampException */ @@ -94,7 +92,7 @@ class Migration extends Event ResqueScheduler::enqueueAt($at, $this->queue, $this->class, [ 'project' => $this->project, 'user' => $this->user, - 'migration' => $this->migration, + 'migration' => $this->migration ]); } } diff --git a/src/Appwrite/Event/Phone.php b/src/Appwrite/Event/Phone.php index 87bee4bc37..8baa5120c9 100644 --- a/src/Appwrite/Event/Phone.php +++ b/src/Appwrite/Event/Phone.php @@ -7,7 +7,6 @@ use Resque; class Phone extends Event { protected string $recipient = ''; - protected string $message = ''; public function __construct() @@ -18,7 +17,7 @@ class Phone extends Event /** * Sets recipient for the messaging event. * - * @param string $recipient + * @param string $recipient * @return self */ public function setRecipient(string $recipient): self @@ -41,7 +40,7 @@ class Phone extends Event /** * Sets url for the messaging event. * - * @param string $message + * @param string $message * @return self */ public function setMessage(string $message): self @@ -65,7 +64,6 @@ class Phone extends Event * Executes the event and sends it to the messaging worker. * * @return string|bool - * * @throws \InvalidArgumentException */ public function trigger(): string|bool @@ -76,7 +74,7 @@ class Phone extends Event 'payload' => $this->payload, 'recipient' => $this->recipient, 'message' => $this->message, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); } } diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index 01f576896b..b302b88808 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -2,15 +2,14 @@ namespace Appwrite\Event; -use Utopia\Database\Document; use Utopia\Queue\Client; use Utopia\Queue\Connection; +use Utopia\Database\Document; class Usage extends Event { protected array $metrics = []; - - protected array $reduce = []; + protected array $reduce = []; public function __construct(protected Connection $connection) { @@ -20,7 +19,7 @@ class Usage extends Event /** * Add reduce. * - * @param Document $document + * @param Document $document * @return self */ public function addReduce(Document $document): self @@ -33,8 +32,8 @@ class Usage extends Event /** * Add metric. * - * @param string $key - * @param int $value + * @param string $key + * @param int $value * @return self */ public function addMetric(string $key, int $value): self @@ -58,7 +57,7 @@ class Usage extends Event return $client->enqueue([ 'project' => $this->getProject(), - 'reduce' => $this->reduce, + 'reduce' => $this->reduce, 'metrics' => $this->metrics, ]); } diff --git a/src/Appwrite/Event/Validator/Event.php b/src/Appwrite/Event/Validator/Event.php index 7e8ef316cc..3f22900486 100644 --- a/src/Appwrite/Event/Validator/Event.php +++ b/src/Appwrite/Event/Validator/Event.php @@ -27,7 +27,8 @@ class Event extends Validator /** * Is valid. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($value): bool @@ -47,7 +48,6 @@ class Event extends Validator if ($type == 'functions') { $this->message = 'Triggering a function on a function event is not allowed.'; - return false; } @@ -55,7 +55,7 @@ class Event extends Validator $hasSubResource = $count > 3 && ($events[$type]['$resource'] ?? false) && ($events[$type][$parts[2]]['$resource'] ?? false); $hasSubSubResource = $count > 5 && $hasSubResource && ($events[$type][$parts[2]][$parts[4]]['$resource'] ?? false); - if (! $type || ! $resource) { + if (!$type || !$resource) { return false; } @@ -72,13 +72,13 @@ class Event extends Validator } } - if ($hasSubResource && ! $hasSubSubResource) { + if ($hasSubResource && !$hasSubSubResource) { if ($count === 6) { $attribute = $parts[5]; } } - if (! $hasSubResource) { + if (!$hasSubResource) { if ($count === 4) { $attribute = $parts[3]; } @@ -91,36 +91,36 @@ class Event extends Validator $attribute ??= false; $action = match (true) { - ! $hasSubResource && $count > 2 => $parts[2], + !$hasSubResource && $count > 2 => $parts[2], $hasSubSubResource => $parts[6] ?? false, $hasSubResource && $count > 4 => $parts[4], default => false }; - if (! \array_key_exists($type, $events)) { + if (!\array_key_exists($type, $events)) { return false; } if ($subType) { - if ($action && ! \array_key_exists($action, $events[$type][$subType])) { + if ($action && !\array_key_exists($action, $events[$type][$subType])) { return false; } - if (! ($subResource) || ! \array_key_exists($subType, $events[$type])) { + if (!($subResource) || !\array_key_exists($subType, $events[$type])) { return false; } } else { - if ($action && ! \array_key_exists($action, $events[$type])) { + if ($action && !\array_key_exists($action, $events[$type])) { return false; } } if ($attribute) { if (($subType)) { - if (! \array_key_exists($attribute, $events[$type][$subType][$action])) { + if (!\array_key_exists($attribute, $events[$type][$subType][$action])) { return false; } } else { - if (! \array_key_exists($attribute, $events[$type][$action])) { + if (!\array_key_exists($attribute, $events[$type][$action])) { return false; } } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 4b1be708c3..d5803f5fbf 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -36,295 +36,187 @@ class Exception extends \Exception */ /** General */ - public const GENERAL_UNKNOWN = 'general_unknown'; - - public const GENERAL_MOCK = 'general_mock'; - - public const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; - - public const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; - - public const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; - - public const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; - - public const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; - - public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; - - public const GENERAL_PHONE_DISABLED = 'general_phone_disabled'; - - public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; - - public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; - - public const GENERAL_QUERY_INVALID = 'general_query_invalid'; - - public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; - - public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; - - public const GENERAL_SERVER_ERROR = 'general_server_error'; - - public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; - - public const GENERAL_CODES_DISABLED = 'general_codes_disabled'; - - public const GENERAL_USAGE_DISABLED = 'general_usage_disabled'; + public const GENERAL_UNKNOWN = 'general_unknown'; + public const GENERAL_MOCK = 'general_mock'; + public const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; + public const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; + public const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; + public const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; + public const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; + public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; + public const GENERAL_PHONE_DISABLED = 'general_phone_disabled'; + public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; + public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; + public const GENERAL_QUERY_INVALID = 'general_query_invalid'; + public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; + public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; + public const GENERAL_SERVER_ERROR = 'general_server_error'; + public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; + public const GENERAL_CODES_DISABLED = 'general_codes_disabled'; + public const GENERAL_USAGE_DISABLED = 'general_usage_disabled'; /** Users */ - public const USER_COUNT_EXCEEDED = 'user_count_exceeded'; - - public const USER_JWT_INVALID = 'user_jwt_invalid'; - - public const USER_ALREADY_EXISTS = 'user_already_exists'; - - public const USER_BLOCKED = 'user_blocked'; - - public const USER_INVALID_TOKEN = 'user_invalid_token'; - - public const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; - - public const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; - - public const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; - - public const USER_INVALID_CODE = 'user_invalid_code'; - - public const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; - + public const USER_COUNT_EXCEEDED = 'user_count_exceeded'; + public const USER_JWT_INVALID = 'user_jwt_invalid'; + public const USER_ALREADY_EXISTS = 'user_already_exists'; + public const USER_BLOCKED = 'user_blocked'; + public const USER_INVALID_TOKEN = 'user_invalid_token'; + public const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; + public const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; + public const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; + public const USER_INVALID_CODE = 'user_invalid_code'; + public const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; public const USER_ANONYMOUS_CONSOLE_PROHIBITED = 'user_anonymous_console_prohibited'; - - public const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; - - public const USER_NOT_FOUND = 'user_not_found'; - - public const USER_PASSWORD_RECENTLY_USED = 'password_recently_used'; - - public const USER_PASSWORD_PERSONAL_DATA = 'password_personal_data'; - - public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; - - public const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; - - public const USER_SESSION_NOT_FOUND = 'user_session_not_found'; - - public const USER_IDENTITY_NOT_FOUND = 'user_identity_not_found'; - - public const USER_UNAUTHORIZED = 'user_unauthorized'; - - public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; - - public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists'; - - public const USER_PHONE_NOT_FOUND = 'user_phone_not_found'; - - public const USER_MISSING_ID = 'user_missing_id'; - - public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; - - public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; - - public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; - - public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; - - public const USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; - + public const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; + public const USER_NOT_FOUND = 'user_not_found'; + public const USER_PASSWORD_RECENTLY_USED = 'password_recently_used'; + public const USER_PASSWORD_PERSONAL_DATA = 'password_personal_data'; + public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; + public const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; + public const USER_SESSION_NOT_FOUND = 'user_session_not_found'; + public const USER_IDENTITY_NOT_FOUND = 'user_identity_not_found'; + public const USER_UNAUTHORIZED = 'user_unauthorized'; + public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; + public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists'; + public const USER_PHONE_NOT_FOUND = 'user_phone_not_found'; + public const USER_MISSING_ID = 'user_missing_id'; + public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; + public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; + public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; + public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; + public const USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; /** Teams */ - public const TEAM_NOT_FOUND = 'team_not_found'; - - public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; - - public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; - - public const TEAM_INVALID_SECRET = 'team_invalid_secret'; - - public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; - - public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; - - public const TEAM_ALREADY_EXISTS = 'team_already_exists'; + public const TEAM_NOT_FOUND = 'team_not_found'; + public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; + public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; + public const TEAM_INVALID_SECRET = 'team_invalid_secret'; + public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; + public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; + public const TEAM_ALREADY_EXISTS = 'team_already_exists'; /** Membership */ - public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; - - public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; + public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; + public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; /** Avatars */ - public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; - - public const AVATAR_NOT_FOUND = 'avatar_not_found'; - - public const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; - - public const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; - - public const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; + public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; + public const AVATAR_NOT_FOUND = 'avatar_not_found'; + public const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; + public const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; + public const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; /** Storage */ - public const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; - - public const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; - - public const STORAGE_FILE_EMPTY = 'storage_file_empty'; - - public const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; - - public const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; - - public const STORAGE_INVALID_FILE = 'storage_invalid_file'; - - public const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; - - public const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; - - public const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; - - public const STORAGE_INVALID_RANGE = 'storage_invalid_range'; - - public const STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; + public const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; + public const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; + public const STORAGE_FILE_EMPTY = 'storage_file_empty'; + public const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; + public const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; + public const STORAGE_INVALID_FILE = 'storage_invalid_file'; + public const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; + public const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; + public const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; + public const STORAGE_INVALID_RANGE = 'storage_invalid_range'; + public const STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; /** Functions */ - public const FUNCTION_NOT_FOUND = 'function_not_found'; - - public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; + public const FUNCTION_NOT_FOUND = 'function_not_found'; + public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; /** Deployments */ - public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; + public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; /** Builds */ - public const BUILD_NOT_FOUND = 'build_not_found'; - - public const BUILD_NOT_READY = 'build_not_ready'; - - public const BUILD_IN_PROGRESS = 'build_in_progress'; + public const BUILD_NOT_FOUND = 'build_not_found'; + public const BUILD_NOT_READY = 'build_not_ready'; + public const BUILD_IN_PROGRESS = 'build_in_progress'; /** Execution */ - public const EXECUTION_NOT_FOUND = 'execution_not_found'; + public const EXECUTION_NOT_FOUND = 'execution_not_found'; /** Databases */ - public const DATABASE_NOT_FOUND = 'database_not_found'; - - public const DATABASE_ALREADY_EXISTS = 'database_already_exists'; + public const DATABASE_NOT_FOUND = 'database_not_found'; + public const DATABASE_ALREADY_EXISTS = 'database_already_exists'; /** Collections */ - public const COLLECTION_NOT_FOUND = 'collection_not_found'; - - public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; - - public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + public const COLLECTION_NOT_FOUND = 'collection_not_found'; + public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; + public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; /** Documents */ - public const DOCUMENT_NOT_FOUND = 'document_not_found'; - - public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; - - public const DOCUMENT_MISSING_DATA = 'document_missing_data'; - - public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; - - public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; - - public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; - - public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; + public const DOCUMENT_NOT_FOUND = 'document_not_found'; + public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; + public const DOCUMENT_MISSING_DATA = 'document_missing_data'; + public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; + public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; + public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; + public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; /** Attribute */ - public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; - - public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; - - public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; - - public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; - - public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; - - public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; - - public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; - - public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; - - public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; + public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; + public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; + public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; + public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; + public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; + public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; + public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; + public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; + public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; /** Indexes */ - public const INDEX_NOT_FOUND = 'index_not_found'; - - public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; - - public const INDEX_ALREADY_EXISTS = 'index_already_exists'; - - public const INDEX_INVALID = 'index_invalid'; + public const INDEX_NOT_FOUND = 'index_not_found'; + public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; + public const INDEX_ALREADY_EXISTS = 'index_already_exists'; + public const INDEX_INVALID = 'index_invalid'; /** Projects */ - public const PROJECT_NOT_FOUND = 'project_not_found'; + public const PROJECT_NOT_FOUND = 'project_not_found'; + public const PROJECT_UNKNOWN = 'project_unknown'; + public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; + public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; + public const PROJECT_ALREADY_EXISTS = 'project_already_exists'; + public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; + public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; + public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; + public const PROJECT_KEY_EXPIRED = 'project_key_expired'; - public const PROJECT_UNKNOWN = 'project_unknown'; - - public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; - - public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; - - public const PROJECT_ALREADY_EXISTS = 'project_already_exists'; - - public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; - - public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; - - public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; - - public const PROJECT_KEY_EXPIRED = 'project_key_expired'; - - public const PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid'; + public const PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid'; public const PROJECT_TEMPLATE_DEFAULT_DELETION = 'project_template_default_deletion'; /** Webhooks */ - public const WEBHOOK_NOT_FOUND = 'webhook_not_found'; + public const WEBHOOK_NOT_FOUND = 'webhook_not_found'; /** Keys */ - public const KEY_NOT_FOUND = 'key_not_found'; + public const KEY_NOT_FOUND = 'key_not_found'; /** Variables */ - public const VARIABLE_NOT_FOUND = 'variable_not_found'; - - public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; + public const VARIABLE_NOT_FOUND = 'variable_not_found'; + public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; /** Platform */ - public const PLATFORM_NOT_FOUND = 'platform_not_found'; + public const PLATFORM_NOT_FOUND = 'platform_not_found'; /** Domain */ - public const DOMAIN_NOT_FOUND = 'domain_not_found'; - - public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; - - public const DOMAIN_FORBIDDEN = 'domain_forbidden'; - - public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; - - public const DOMAIN_TARGET_INVALID = 'domain_target_invalid'; + public const DOMAIN_NOT_FOUND = 'domain_not_found'; + public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; + public const DOMAIN_FORBIDDEN = 'domain_forbidden'; + public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; + public const DOMAIN_TARGET_INVALID = 'domain_target_invalid'; /** GraphqQL */ - public const GRAPHQL_NO_QUERY = 'graphql_no_query'; - - public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; + public const GRAPHQL_NO_QUERY = 'graphql_no_query'; + public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; /** Migrations */ - public const MIGRATION_NOT_FOUND = 'migration_not_found'; - - public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists'; - - public const MIGRATION_IN_PROGRESS = 'migration_in_progress'; + public const MIGRATION_NOT_FOUND = 'migration_not_found'; + public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists'; + public const MIGRATION_IN_PROGRESS = 'migration_in_progress'; /** Provider */ - public const PROVIDER_NOT_FOUND = 'provider_not_found'; - - public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; + public const PROVIDER_NOT_FOUND = 'provider_not_found'; + public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; protected $type = ''; - protected $errors = []; public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int $code = null, \Throwable $previous = null) @@ -356,7 +248,8 @@ class Exception extends \Exception /** * Set the type of the exception. * - * @param string $type + * @param string $type + * * @return void */ public function setType(string $type): void diff --git a/src/Appwrite/GraphQL/Promises/Adapter.php b/src/Appwrite/GraphQL/Promises/Adapter.php index 0051dbe612..86270f2a8b 100644 --- a/src/Appwrite/GraphQL/Promises/Adapter.php +++ b/src/Appwrite/GraphQL/Promises/Adapter.php @@ -22,15 +22,14 @@ abstract class Adapter implements PromiseAdapter /** * Converts a {@see Promise} into a {@see GQLPromise} * - * @param mixed $thenable + * @param mixed $thenable * @return GQLPromise - * * @throws \Exception */ public function convertThenable(mixed $thenable): GQLPromise { - if (! $thenable instanceof Promise) { - throw new \Exception('Expected instance of Promise got: '.\gettype($thenable)); + if (!$thenable instanceof Promise) { + throw new \Exception('Expected instance of Promise got: ' . \gettype($thenable)); } return new GQLPromise($thenable, $this); @@ -39,9 +38,9 @@ abstract class Adapter implements PromiseAdapter /** * Returns a promise that resolves when the passed in promise resolves. * - * @param GQLPromise $promise - * @param callable|null $onFulfilled - * @param callable|null $onRejected + * @param GQLPromise $promise + * @param callable|null $onFulfilled + * @param callable|null $onRejected * @return GQLPromise */ public function then( @@ -58,7 +57,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise with the given resolver function. * - * @param callable $resolver + * @param callable $resolver * @return GQLPromise */ abstract public function create(callable $resolver): GQLPromise; @@ -66,7 +65,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise that is fulfilled with the given value. * - * @param mixed $value + * @param mixed $value * @return GQLPromise */ abstract public function createFulfilled(mixed $value = null): GQLPromise; @@ -74,7 +73,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise that is rejected with the given reason. * - * @param mixed $reason + * @param mixed $reason * @return GQLPromise */ abstract public function createRejected(mixed $reason): GQLPromise; @@ -82,7 +81,7 @@ abstract class Adapter implements PromiseAdapter /** * Create a new promise that resolves when all passed in promises resolve. * - * @param array $promisesOrValues + * @param array $promisesOrValues * @return GQLPromise */ abstract public function all(array $promisesOrValues): GQLPromise; diff --git a/src/Appwrite/GraphQL/Resolvers.php b/src/Appwrite/GraphQL/Resolvers.php index 3c5ba4b310..c143a93554 100644 --- a/src/Appwrite/GraphQL/Resolvers.php +++ b/src/Appwrite/GraphQL/Resolvers.php @@ -15,28 +15,28 @@ class Resolvers /** * Create a resolver for a given API {@see Route}. * - * @param App $utopia - * @param ?Route $route + * @param App $utopia + * @param ?Route $route * @return callable */ public static function api( App $utopia, ?Route $route, - ): callable - { - return static fn ($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $route, $args) { + ): callable { + return static fn($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $route, $args, $context, $info) { /** @var App $utopia */ /** @var Response $response */ /** @var Request $request */ + $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); $path = $route->getPath(); foreach ($args as $key => $value) { - if (\str_contains($path, '/:'.$key)) { - $path = \str_replace(':'.$key, $value, $path); + if (\str_contains($path, '/:' . $key)) { + $path = \str_replace(':' . $key, $value, $path); } } @@ -60,10 +60,10 @@ class Resolvers /** * Create a resolver for a document in a specified database and collection with a specific method type. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param string $methodType + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param string $methodType * @return callable */ public static function document( @@ -71,9 +71,8 @@ class Resolvers string $databaseId, string $collectionId, string $methodType, - ): callable - { - return [self::class, 'document'.\ucfirst($methodType)]( + ): callable { + return [self::class, 'document' . \ucfirst($methodType)]( $utopia, $databaseId, $collectionId @@ -83,10 +82,10 @@ class Resolvers /** * Create a resolver for getting a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url * @return callable */ public static function documentGet( @@ -94,10 +93,9 @@ class Resolvers string $databaseId, string $collectionId, callable $url, - ): callable - { - return static fn ($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $args) { + ): callable { + return static fn($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $type, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -113,11 +111,11 @@ class Resolvers /** * Create a resolver for listing documents in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url - * @param callable $params + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url + * @param callable $params * @return callable */ public static function documentList( @@ -126,10 +124,9 @@ class Resolvers string $collectionId, callable $url, callable $params, - ): callable - { - return static fn ($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) { + ): callable { + return static fn($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -150,11 +147,11 @@ class Resolvers /** * Create a resolver for creating a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url - * @param callable $params + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url + * @param callable $params * @return callable */ public static function documentCreate( @@ -163,10 +160,9 @@ class Resolvers string $collectionId, callable $url, callable $params, - ): callable - { - return static fn ($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) { + ): callable { + return static fn($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -183,11 +179,11 @@ class Resolvers /** * Create a resolver for updating a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url - * @param callable $params + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url + * @param callable $params * @return callable */ public static function documentUpdate( @@ -196,10 +192,9 @@ class Resolvers string $collectionId, callable $url, callable $params, - ): callable - { - return static fn ($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) { + ): callable { + return static fn($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -216,10 +211,10 @@ class Resolvers /** * Create a resolver for deleting a document in a specified database and collection. * - * @param App $utopia - * @param string $databaseId - * @param string $collectionId - * @param callable $url + * @param App $utopia + * @param string $databaseId + * @param string $collectionId + * @param callable $url * @return callable */ public static function documentDelete( @@ -227,10 +222,9 @@ class Resolvers string $databaseId, string $collectionId, callable $url, - ): callable - { - return static fn ($type, $args, $context, $info) => new Swoole( - function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $args) { + ): callable { + return static fn($type, $args, $context, $info) => new Swoole( + function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $type, $args) { $utopia = $utopia->getResource('utopia:graphql', true); $request = $utopia->getResource('request', true); $response = $utopia->getResource('response', true); @@ -244,15 +238,14 @@ class Resolvers } /** - * @param App $utopia - * @param Request $request - * @param Response $response - * @param callable $resolve - * @param callable $reject - * @param callable|null $beforeResolve - * @param callable|null $beforeReject + * @param App $utopia + * @param Request $request + * @param Response $response + * @param callable $resolve + * @param callable $reject + * @param callable|null $beforeResolve + * @param callable|null $beforeReject * @return void - * * @throws Exception */ private static function resolve( @@ -270,7 +263,7 @@ class Resolvers } $request = clone $request; - $utopia->setResource('request', static fn () => $request); + $utopia->setResource('request', static fn() => $request); $response->setContentType(Response::CONTENT_TYPE_NULL); try { @@ -282,7 +275,6 @@ class Resolvers $e = $beforeReject($e); } $reject($e); - return; } @@ -296,7 +288,6 @@ class Resolvers message: $payload['message'], code: $response->getStatusCode() )); - return; } diff --git a/src/Appwrite/GraphQL/Schema.php b/src/Appwrite/GraphQL/Schema.php index 608369ef80..11f728e571 100644 --- a/src/Appwrite/GraphQL/Schema.php +++ b/src/Appwrite/GraphQL/Schema.php @@ -13,17 +13,16 @@ use Utopia\Route; class Schema { protected static ?GQLSchema $schema = null; - protected static array $dirty = []; /** - * @param App $utopia - * @param callable $complexity Function to calculate complexity - * @param callable $attributes Function to get attributes - * @param array $urls Array of functions to get urls for specific method types - * @param array $params Array of functions to build parameters for specific method types - * @return GQLSchema * + * @param App $utopia + * @param callable $complexity Function to calculate complexity + * @param callable $attributes Function to get attributes + * @param array $urls Array of functions to get urls for specific method types + * @param array $params Array of functions to build parameters for specific method types + * @return GQLSchema * @throws Exception */ public static function build( @@ -37,7 +36,7 @@ class Schema return $utopia; }); - if (! empty(self::$schema)) { + if (!empty(self::$schema)) { return self::$schema; } @@ -68,12 +67,12 @@ class Schema return static::$schema = new GQLSchema([ 'query' => new ObjectType([ 'name' => 'Query', - 'fields' => $queries, + 'fields' => $queries ]), 'mutation' => new ObjectType([ 'name' => 'Mutation', - 'fields' => $mutations, - ]), + 'fields' => $mutations + ]) ]); } @@ -81,10 +80,9 @@ class Schema * This function iterates all API routes and builds a GraphQL * schema defining types and resolvers for all response models. * - * @param App $utopia - * @param callable $complexity + * @param App $utopia + * @param callable $complexity * @return array - * * @throws Exception */ protected static function api(App $utopia, callable $complexity): array @@ -99,9 +97,10 @@ class Schema foreach ($utopia->getRoutes() as $routes) { foreach ($routes as $route) { /** @var Route $route */ + $namespace = $route->getLabel('sdk.namespace', ''); $method = $route->getLabel('sdk.method', ''); - $name = $namespace.\ucfirst($method); + $name = $namespace . \ucfirst($method); if (empty($name)) { continue; @@ -127,7 +126,7 @@ class Schema return [ 'query' => $queries, - 'mutation' => $mutations, + 'mutation' => $mutations ]; } @@ -135,13 +134,12 @@ class Schema * Iterates all of a projects attributes and builds GraphQL * queries and mutations for the collections they make up. * - * @param App $utopia - * @param callable $complexity - * @param callable $attributes - * @param array $urls - * @param array $params + * @param App $utopia + * @param callable $complexity + * @param callable $attributes + * @param array $urls + * @param array $params * @return array - * * @throws \Exception */ protected static function collections( @@ -157,7 +155,7 @@ class Schema $limit = 1000; $offset = 0; - while (! empty($attrs = $attributes($limit, $offset))) { + while (!empty($attrs = $attributes($limit, $offset))) { foreach ($attrs as $attr) { if ($attr['status'] !== 'available') { continue; @@ -184,7 +182,7 @@ class Schema $objectType = new ObjectType([ 'name' => $collectionId, 'fields' => \array_merge( - ['_id' => ['type' => Type::string()]], + ["_id" => ['type' => Type::string()]], $attributes ), ]); @@ -193,7 +191,7 @@ class Schema Mapper::args('mutate') ); - $queryFields[$collectionId.'Get'] = [ + $queryFields[$collectionId . 'Get'] = [ 'type' => $objectType, 'args' => Mapper::args('id'), 'resolve' => Resolvers::documentGet( @@ -201,9 +199,9 @@ class Schema $databaseId, $collectionId, $urls['get'], - ), + ) ]; - $queryFields[$collectionId.'List'] = [ + $queryFields[$collectionId . 'List'] = [ 'type' => Type::listOf($objectType), 'args' => Mapper::args('list'), 'resolve' => Resolvers::documentList( @@ -216,7 +214,7 @@ class Schema 'complexity' => $complexity, ]; - $mutationFields[$collectionId.'Create'] = [ + $mutationFields[$collectionId . 'Create'] = [ 'type' => $objectType, 'args' => $attributes, 'resolve' => Resolvers::documentCreate( @@ -225,14 +223,14 @@ class Schema $collectionId, $urls['create'], $params['create'], - ), + ) ]; - $mutationFields[$collectionId.'Update'] = [ + $mutationFields[$collectionId . 'Update'] = [ 'type' => $objectType, 'args' => \array_merge( Mapper::args('id'), \array_map( - fn ($attr) => $attr['type'] = Type::getNullableType($attr['type']), + fn($attr) => $attr['type'] = Type::getNullableType($attr['type']), $attributes ) ), @@ -242,9 +240,9 @@ class Schema $collectionId, $urls['update'], $params['update'], - ), + ) ]; - $mutationFields[$collectionId.'Delete'] = [ + $mutationFields[$collectionId . 'Delete'] = [ 'type' => Mapper::model('none'), 'args' => Mapper::args('id'), 'resolve' => Resolvers::documentDelete( @@ -252,7 +250,7 @@ class Schema $databaseId, $collectionId, $urls['delete'], - ), + ) ]; } $offset += $limit; @@ -260,7 +258,7 @@ class Schema return [ 'query' => $queryFields, - 'mutation' => $mutationFields, + 'mutation' => $mutationFields ]; } diff --git a/src/Appwrite/GraphQL/Types.php b/src/Appwrite/GraphQL/Types.php index b20c4cb32e..279cac2068 100644 --- a/src/Appwrite/GraphQL/Types.php +++ b/src/Appwrite/GraphQL/Types.php @@ -22,7 +22,6 @@ class Types } $type = new Json(); Registry::set(Json::class, $type); - return $type; } @@ -38,7 +37,6 @@ class Types } $type = new Assoc(); Registry::set(Assoc::class, $type); - return $type; } @@ -54,7 +52,6 @@ class Types } $type = new InputFile(); Registry::set(InputFile::class, $type); - return $type; } } diff --git a/src/Appwrite/GraphQL/Types/Assoc.php b/src/Appwrite/GraphQL/Types/Assoc.php index 58584ff60f..a2099f9b22 100644 --- a/src/Appwrite/GraphQL/Types/Assoc.php +++ b/src/Appwrite/GraphQL/Types/Assoc.php @@ -2,13 +2,19 @@ namespace Appwrite\GraphQL\Types; +use GraphQL\Language\AST\BooleanValueNode; +use GraphQL\Language\AST\FloatValueNode; +use GraphQL\Language\AST\IntValueNode; +use GraphQL\Language\AST\ListValueNode; use GraphQL\Language\AST\Node; +use GraphQL\Language\AST\ObjectValueNode; +use GraphQL\Language\AST\StringValueNode; +use GraphQL\Type\Definition\ScalarType; // https://github.com/webonyx/graphql-php/issues/129#issuecomment-309366803 class Assoc extends Json { public $name = 'Assoc'; - public $description = 'The `Assoc` scalar type represents associative array values.'; public function serialize($value) diff --git a/src/Appwrite/GraphQL/Types/InputFile.php b/src/Appwrite/GraphQL/Types/InputFile.php index 6d55ab5359..39fd4e23b3 100644 --- a/src/Appwrite/GraphQL/Types/InputFile.php +++ b/src/Appwrite/GraphQL/Types/InputFile.php @@ -9,7 +9,6 @@ use GraphQL\Type\Definition\ScalarType; class InputFile extends ScalarType { public $name = 'InputFile'; - public $description = 'The `InputFile` special type represents a file to be uploaded in the same HTTP request as specified by [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec).'; @@ -25,6 +24,6 @@ class InputFile extends ScalarType public function parseLiteral(Node $valueNode, ?array $variables = null) { - throw new Error('`InputFile` cannot be hardcoded in query, be sure to conform to GraphQL multipart request specification. Instead got: '.$valueNode->kind, $valueNode); + throw new Error('`InputFile` cannot be hardcoded in query, be sure to conform to GraphQL multipart request specification. Instead got: ' . $valueNode->kind, $valueNode); } } diff --git a/src/Appwrite/GraphQL/Types/Json.php b/src/Appwrite/GraphQL/Types/Json.php index 305432cb90..18d27322a1 100644 --- a/src/Appwrite/GraphQL/Types/Json.php +++ b/src/Appwrite/GraphQL/Types/Json.php @@ -15,7 +15,6 @@ use GraphQL\Type\Definition\ScalarType; class Json extends ScalarType { public $name = 'Json'; - public $description = 'The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).'; @@ -44,9 +43,8 @@ class Json extends ScalarType $value[$field->name->value] = $this->parseLiteral($field->value); } - return $value; - case $valueNode instanceof ListValueNode: + case ($valueNode instanceof ListValueNode): return array_map([$this, 'parseLiteral'], $valueNode->values); default: return null; diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 1c03074f23..0be60d93dc 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -16,9 +16,7 @@ use Utopia\Validator\Nullable; class Mapper { private static array $models = []; - private static array $args = []; - private static array $blacklist = [ '/v1/mock', '/v1/graphql', @@ -45,7 +43,7 @@ class Mapper 'permissions' => [ 'type' => Type::listOf(Type::nonNull(Type::string())), 'defaultValue' => [], - ], + ] ], ]; @@ -68,7 +66,7 @@ class Mapper /** * Get the registered default arguments for a given key. * - * @param string $key + * @param string $key * @return array */ public static function args(string $key): array @@ -89,7 +87,7 @@ class Mapper $names = $route->getLabel('sdk.response.model', 'none'); $models = \is_array($names) - ? \array_map(static fn ($m) => static::$models[$m], $names) + ? \array_map(static fn($m) => static::$models[$m], $names) : [static::$models[$names]]; foreach ($models as $model) { @@ -105,7 +103,7 @@ class Mapper $parameterType = Mapper::param( $utopia, $parameter['validator'], - ! $parameter['optional'], + !$parameter['optional'], $parameter['injections'] ); $params[$name] = [ @@ -118,7 +116,7 @@ class Mapper 'type' => $type, 'description' => $description, 'args' => $params, - 'resolve' => Resolvers::api($utopia, $route), + 'resolve' => Resolvers::api($utopia, $route) ]; if ($list) { @@ -132,7 +130,7 @@ class Mapper /** * Get a type from the registry, creating it if it does not already exist. * - * @param string $name + * @param string $name * @return Type */ public static function model(string $name): Type @@ -151,23 +149,23 @@ class Mapper 'description' => 'Additional data', 'resolve' => static function ($object, $args, $context, $info) { $data = \array_filter( - (array) $object, - fn ($key) => ! \str_starts_with($key, '_'), + (array)$object, + fn($key) => !\str_starts_with($key, '_'), ARRAY_FILTER_USE_KEY ); return \json_encode($data, JSON_FORCE_OBJECT); - }, + } ]; } // If model has no properties, explicitly add a 'status' field // because GraphQL requires at least 1 field per type. - if (! $model->isAny() && empty($model->getRules())) { + if (!$model->isAny() && empty($model->getRules())) { $fields['status'] = [ 'type' => Type::string(), 'description' => 'Status', - 'resolve' => static fn ($object, $args, $context, $info) => 'OK', + 'resolve' => static fn($object, $args, $context, $info) => 'OK', ]; } @@ -189,7 +187,7 @@ class Mapper 'description' => $rule['description'], ]; - if (! $rule['required']) { + if (!$rule['required']) { $fields[$escapedKey]['defaultValue'] = $rule['default']; } } @@ -207,12 +205,11 @@ class Mapper /** * Map a {@see Route} parameter to a GraphQL Type * - * @param App $utopia - * @param Validator|callable $validator - * @param bool $required - * @param array $injections + * @param App $utopia + * @param Validator|callable $validator + * @param bool $required + * @param array $injections * @return Type - * * @throws Exception */ public static function param( @@ -231,7 +228,7 @@ class Mapper $validator = $validator->getValidator(); } - switch ((! empty($validator)) ? $validator::class : '') { + switch ((!empty($validator)) ? $validator::class : '') { case 'Appwrite\Network\Validator\CNAME': case 'Appwrite\Task\Validator\Cron': case 'Appwrite\Utopia\Database\Validator\CustomId': @@ -303,7 +300,7 @@ class Mapper break; } - if ($required && ! $isNullable) { + if ($required && !$isNullable) { $type = Type::nonNull($type); } @@ -313,11 +310,10 @@ class Mapper /** * Map an {@see Attribute} to a GraphQL Type * - * @param string $type - * @param bool $array - * @param bool $required + * @param string $type + * @param bool $array + * @param bool $required * @return Type - * * @throws Exception */ public static function attribute(string $type, bool $array, bool $required): Type @@ -353,7 +349,6 @@ class Mapper } $complexModel = self::$models[$type]; - return self::model(\ucfirst($complexModel->getType())); } @@ -394,7 +389,7 @@ class Mapper return static::getHashOptionsImplementation($object); } - throw new Exception('Unknown union type: '.$name); + throw new Exception('Unknown union type: ' . $name); } private static function getAttributeImplementation(array $object): Type diff --git a/src/Appwrite/GraphQL/Types/Registry.php b/src/Appwrite/GraphQL/Types/Registry.php index 325766bb67..cd40d5c3e4 100644 --- a/src/Appwrite/GraphQL/Types/Registry.php +++ b/src/Appwrite/GraphQL/Types/Registry.php @@ -11,7 +11,7 @@ class Registry /** * Check if a type exists in the registry. * - * @param string $type + * @param string $type * @return bool */ public static function has(string $type): bool @@ -22,7 +22,7 @@ class Registry /** * Get a type from the registry. * - * @param string $type + * @param string $type * @return Type */ public static function get(string $type): Type @@ -33,8 +33,8 @@ class Registry /** * Set a type in the registry. * - * @param string $type - * @param Type $typeObject + * @param string $type + * @param Type $typeObject */ public static function set(string $type, Type $typeObject): void { diff --git a/src/Appwrite/Messaging/Adapter.php b/src/Appwrite/Messaging/Adapter.php index 794fd9b3ed..27dd7f68eb 100644 --- a/src/Appwrite/Messaging/Adapter.php +++ b/src/Appwrite/Messaging/Adapter.php @@ -5,8 +5,6 @@ namespace Appwrite\Messaging; abstract class Adapter { abstract public function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void; - abstract public function unsubscribe(mixed $identifier): void; - abstract public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void; } diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 2824f948d7..33fe484c13 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -2,10 +2,10 @@ namespace Appwrite\Messaging\Adapter; -use Appwrite\Messaging\Adapter; -use Utopia\App; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Appwrite\Messaging\Adapter; +use Utopia\App; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -39,20 +39,20 @@ class Realtime extends Adapter /** * Adds a subscription. * - * @param string $projectId - * @param mixed $identifier - * @param array $roles - * @param array $channels + * @param string $projectId + * @param mixed $identifier + * @param array $roles + * @param array $channels * @return void */ public function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void { - if (! isset($this->subscriptions[$projectId])) { // Init Project + if (!isset($this->subscriptions[$projectId])) { // Init Project $this->subscriptions[$projectId] = []; } foreach ($roles as $role) { - if (! isset($this->subscriptions[$projectId][$role])) { // Add user first connection + if (!isset($this->subscriptions[$projectId][$role])) { // Add user first connection $this->subscriptions[$projectId][$role] = []; } @@ -64,14 +64,14 @@ class Realtime extends Adapter $this->connections[$identifier] = [ 'projectId' => $projectId, 'roles' => $roles, - 'channels' => $channels, + 'channels' => $channels ]; } /** * Removes Subscription. * - * @param mixed $connection + * @param mixed $connection * @return void */ public function unsubscribe(mixed $connection): void @@ -102,10 +102,9 @@ class Realtime extends Adapter /** * Checks if Channel has a subscriber. - * - * @param string $projectId - * @param string $role - * @param string $channel + * @param string $projectId + * @param string $role + * @param string $channel * @return bool */ public function hasSubscriber(string $projectId, string $role, string $channel = ''): bool @@ -123,13 +122,12 @@ class Realtime extends Adapter /** * Sends an event to the Realtime Server - * - * @param string $projectId - * @param array $payload - * @param string $event - * @param array $channels - * @param array $roles - * @param array $options + * @param string $projectId + * @param array $payload + * @param string $event + * @param array $channels + * @param array $roles + * @param array $options * @return void */ public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void @@ -152,8 +150,8 @@ class Realtime extends Adapter 'events' => $events, 'channels' => $channels, 'timestamp' => DateTime::formatTz(DateTime::now()), - 'payload' => $payload, - ], + 'payload' => $payload + ] ])); } @@ -168,10 +166,11 @@ class Realtime extends Adapter * - 110.201 ms (±2.32%) | 100,000 Connections / 1,000,000 Subscriptions * - 1,121.328 ms (±0.84%) | 1,000,000 Connections / 10,000,000 Subscriptions * - * @param array $event + * @param array $event */ public function getSubscribers(array $event) { + $receivers = []; /** * Check if project has subscriber. @@ -213,9 +212,8 @@ class Realtime extends Adapter /** * Converts the channels from the Query Params into an array. * Also renames the account channel to account.USER_ID and removes all illegal account channel variations. - * - * @param array $channels - * @param string $userId + * @param array $channels + * @param string $userId * @return array */ public static function convertChannels(array $channels, string $userId): array @@ -229,8 +227,8 @@ class Realtime extends Adapter break; case $key === 'account': - if (! empty($userId)) { - $channels['account.'.$userId] = $value; + if (!empty($userId)) { + $channels['account.' . $userId] = $value; } break; } @@ -242,9 +240,9 @@ class Realtime extends Adapter /** * Create channels array based on the event name and payload. * - * @param string $event - * @param Document $payload - * @param Document|null $project + * @param string $event + * @param Document $payload + * @param Document|null $project * @return array */ public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array @@ -259,18 +257,18 @@ class Realtime extends Adapter switch ($parts[0]) { case 'users': $channels[] = 'account'; - $channels[] = 'account.'.$parts[1]; + $channels[] = 'account.' . $parts[1]; $roles = [Role::user(ID::custom($parts[1]))->toString()]; break; case 'teams': if ($parts[2] === 'memberships') { $permissionsChanged = $parts[4] ?? false; $channels[] = 'memberships'; - $channels[] = 'memberships.'.$parts[3]; + $channels[] = 'memberships.' . $parts[3]; } else { $permissionsChanged = $parts[2] === 'create'; $channels[] = 'teams'; - $channels[] = 'teams.'.$parts[1]; + $channels[] = 'teams.' . $parts[1]; } $roles = [Role::team(ID::custom($parts[1]))->toString()]; break; @@ -288,8 +286,8 @@ class Realtime extends Adapter } $channels[] = 'documents'; - $channels[] = 'databases.'.$database->getId().'.collections.'.$payload->getAttribute('$collectionId').'.documents'; - $channels[] = 'databases.'.$database->getId().'.collections.'.$payload->getAttribute('$collectionId').'.documents.'.$payload->getId(); + $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents'; + $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId(); $roles = $collection->getAttribute('documentSecurity', false) ? \array_merge($collection->getRead(), $payload->getRead()) @@ -302,8 +300,8 @@ class Realtime extends Adapter throw new \Exception('Bucket needs to be passed to Realtime for File events in the Storage.'); } $channels[] = 'files'; - $channels[] = 'buckets.'.$payload->getAttribute('bucketId').'.files'; - $channels[] = 'buckets.'.$payload->getAttribute('bucketId').'.files.'.$payload->getId(); + $channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files'; + $channels[] = 'buckets.' . $payload->getAttribute('bucketId') . '.files.' . $payload->getId(); $roles = $bucket->getAttribute('fileSecurity', false) ? \array_merge($bucket->getRead(), $payload->getRead()) @@ -314,11 +312,11 @@ class Realtime extends Adapter case 'functions': if ($parts[2] === 'executions') { - if (! empty($payload->getRead())) { + if (!empty($payload->getRead())) { $channels[] = 'console'; $channels[] = 'executions'; - $channels[] = 'executions.'.$payload->getId(); - $channels[] = 'functions.'.$payload->getAttribute('functionId'); + $channels[] = 'executions.' . $payload->getId(); + $channels[] = 'functions.' . $payload->getAttribute('functionId'); $roles = $payload->getRead(); } } elseif ($parts[2] === 'deployments') { @@ -334,7 +332,7 @@ class Realtime extends Adapter 'channels' => $channels, 'roles' => $roles, 'permissionsChanged' => $permissionsChanged, - 'projectId' => $projectId, + 'projectId' => $projectId ]; } } diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 2685d81829..9ea3443091 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -2,15 +2,15 @@ namespace Appwrite\Migration; -use Exception; use Swoole\Runtime; -use Utopia\App; +use Utopia\Database\Document; +use Utopia\Database\Database; +use Utopia\Database\Query; use Utopia\CLI\Console; use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\Document; +use Exception; +use Utopia\App; use Utopia\Database\Helpers\ID; -use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; Runtime::enableCoroutine(SWOOLE_HOOK_ALL); @@ -80,25 +80,26 @@ abstract class Migration $this->collections = array_merge([ '_metadata' => [ '$id' => ID::custom('_metadata'), - '$collection' => Database::METADATA, + '$collection' => Database::METADATA ], 'audit' => [ '$id' => ID::custom('audit'), - '$collection' => Database::METADATA, + '$collection' => Database::METADATA ], 'abuse' => [ '$id' => ID::custom('abuse'), - '$collection' => Database::METADATA, - ], + '$collection' => Database::METADATA + ] ], Config::getParam('collections', [])); } /** * Set project for migration. * - * @param Document $project - * @param Database $projectDB - * @param Database $oldConsoleDB + * @param Document $project + * @param Database $projectDB + * @param Database $oldConsoleDB + * * @return self */ public function setProject(Document $project, Database $projectDB, Database $consoleDB): self @@ -113,7 +114,7 @@ abstract class Migration /** * Set PDO for Migration. * - * @param \PDO $pdo + * @param \PDO $pdo * @return \Appwrite\Migration\Migration */ public function setPDO(\PDO $pdo): self @@ -126,7 +127,7 @@ abstract class Migration /** * Iterates through every document. * - * @param callable $callback + * @param callable $callback */ public function forEachDocument(callable $callback): void { @@ -135,7 +136,7 @@ abstract class Migration continue; } - Console::log('Migrating Collection '.$collection['$id'].':'); + Console::log('Migrating Collection ' . $collection['$id'] . ':'); \Co\run(function (array $collection, callable $callback) { foreach ($this->documentsIterator($collection['$id']) as $document) { @@ -147,15 +148,14 @@ abstract class Migration $old = $document->getArrayCopy(); $new = call_user_func($callback, $document); - if (is_null($new) || ! self::hasDifference($new->getArrayCopy(), $old)) { + if (is_null($new) || !self::hasDifference($new->getArrayCopy(), $old)) { return; } try { $new = $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); } catch (\Throwable $th) { - Console::error('Failed to update document: '.$th->getMessage()); - + Console::error('Failed to update document: ' . $th->getMessage()); return; } }, $document, $callback); @@ -167,9 +167,8 @@ abstract class Migration /** * Provides an iterator for all documents on a collection. * - * @param string $collectionId + * @param string $collectionId * @return iterable - * * @throws \Exception */ public function documentsIterator(string $collectionId): iterable @@ -187,7 +186,7 @@ abstract class Migration $count = count($documents); $sum += $count; - Console::log($sum.' / '.$collectionCount); + Console::log($sum . ' / ' . $collectionCount); foreach ($documents as $document) { yield $document; } @@ -197,28 +196,28 @@ abstract class Migration } else { $nextDocument = end($documents); } - } while (! is_null($nextDocument)); + } while (!is_null($nextDocument)); } /** * Checks 2 arrays for differences. * - * @param array $array1 - * @param array $array2 + * @param array $array1 + * @param array $array2 * @return bool */ public static function hasDifference(array $array1, array $array2): bool { foreach ($array1 as $key => $value) { if (is_array($value)) { - if (! isset($array2[$key]) || ! is_array($array2[$key])) { + if (!isset($array2[$key]) || !is_array($array2[$key])) { return true; } else { if (self::hasDifference($value, $array2[$key])) { return true; } } - } elseif (! array_key_exists($key, $array2) || $array2[$key] !== $value) { + } elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) { return true; } } @@ -229,17 +228,16 @@ abstract class Migration /** * Creates colletion from the config collection. * - * @param string $id - * @param string|null $name + * @param string $id + * @param string|null $name * @return void - * * @throws \Throwable */ protected function createCollection(string $id, string $name = null): void { $name ??= $id; - if (! $this->projectDB->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { + if (!$this->projectDB->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { $attributes = []; $indexes = []; $collection = $this->collections[$id]; @@ -277,11 +275,10 @@ abstract class Migration /** * Creates attribute from collections.php * - * @param \Utopia\Database\Database $database - * @param string $collectionId - * @param string $attributeId + * @param \Utopia\Database\Database $database + * @param string $collectionId + * @param string $attributeId * @return void - * * @throws \Exception * @throws \Utopia\Database\Exception\Duplicate * @throws \Utopia\Database\Exception\Limit @@ -323,12 +320,11 @@ abstract class Migration /** * Creates index from collections.php * - * @param \Utopia\Database\Database $database - * @param string $collectionId - * @param string $indexId - * @param string|null $from + * @param \Utopia\Database\Database $database + * @param string $collectionId + * @param string $indexId + * @param string|null $from * @return void - * * @throws \Exception * @throws \Utopia\Database\Exception\Duplicate * @throws \Utopia\Database\Exception\Limit @@ -364,9 +360,9 @@ abstract class Migration /** * Change a collection attribute's internal type * - * @param string $collection - * @param string $attribute - * @param string $type + * @param string $collection + * @param string $attribute + * @param string $type * @return void */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index dadf971675..b6deb780da 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -4,6 +4,8 @@ namespace Appwrite\Migration\Version; use Appwrite\Migration\Migration; use Appwrite\OpenSSL\OpenSSL; +use Exception; +use PDO; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -31,7 +33,7 @@ class V15 extends Migration $this->providers = \array_merge( ['email', 'anonymous'], \array_map( - fn ($value) => 'oauth-'.$value, + fn ($value) => "oauth-" . $value, \array_keys(Config::getParam('authProviders', [])) ) ); @@ -47,7 +49,7 @@ class V15 extends Migration ); } - Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); Console::info('Migrating Stats'); $this->migrateStatsMetric('requests', 'project.$all.network.requests'); $this->migrateStatsMetric('network', 'project.$all.network.bandwidth'); @@ -74,7 +76,6 @@ class V15 extends Migration * Migrating all Bucket tables. * * @return void - * * @throws \Exception * @throws \PDOException */ @@ -107,7 +108,7 @@ class V15 extends Migration addCreatePermission: true ); - if (! is_null($bucket->getAttribute('permission'))) { + if (!is_null($bucket->getAttribute('permission'))) { $bucket->setAttribute('fileSecurity', $bucket->getAttribute('permissions') === 'document'); } @@ -151,7 +152,6 @@ class V15 extends Migration * Migrating all Database and Collection tables. * * @return void - * * @throws \Exception * @throws \PDOException */ @@ -229,7 +229,7 @@ class V15 extends Migration addCreatePermission: true ); - if (! is_null($collection->getAttribute('permission'))) { + if (!is_null($collection->getAttribute('permission'))) { $collection->setAttribute('documentSecurity', $collection->getAttribute('permissions') === 'document'); } @@ -249,10 +249,9 @@ class V15 extends Migration $requiredAttributes = array_reduce($collection->getAttribute('attributes', []), function (array $carry, Document $item) { if ($item->getAttribute('required', false)) { $carry = array_merge($carry, [ - $item->getAttribute('key') => $item->getAttribute('default'), + $item->getAttribute('key') => $item->getAttribute('default') ]); } - return $carry; }, []); @@ -290,7 +289,7 @@ class V15 extends Migration /** * Removes all 'write' permissions from a table. * - * @param string $table + * @param string $table * @return void */ protected function removeWritePermissions(string $table): void @@ -305,9 +304,8 @@ class V15 extends Migration /** * Returns all columns from the Table. * - * @param string $table + * @param string $table * @return array - * * @throws \Exception * @throws \PDOException */ @@ -327,7 +325,6 @@ class V15 extends Migration * Migrates all Integer colums for timestamps to DateTime. * * @return void - * * @throws \Exception */ protected function migrateDateTimeAttribute(string $table, string $attribute): void @@ -355,7 +352,7 @@ class V15 extends Migration /** * Skip adding filter on internal attributes. */ - if (! str_starts_with($attribute, '_')) { + if (!str_starts_with($attribute, '_')) { try { /** * Add datetime filter. @@ -381,9 +378,8 @@ class V15 extends Migration /** * Create the '_permissions' column to a table. * - * @param string $table + * @param string $table * @return void - * * @throws \Exception * @throws \PDOException */ @@ -391,7 +387,7 @@ class V15 extends Migration { $columns = $this->getSQLColumnTypes($table); - if (! array_key_exists('_permissions', $columns)) { + if (!array_key_exists('_permissions', $columns)) { try { $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { @@ -403,11 +399,10 @@ class V15 extends Migration /** * Populate '$permissions' from '$read' and '$write'. * - * @param \Utopia\Database\Document $document - * @param null|string $table - * @param bool $addCreatePermission + * @param \Utopia\Database\Document $document + * @param null|string $table + * @param bool $addCreatePermission * @return void - * * @throws \Exception * @throws \PDOException */ @@ -448,7 +443,7 @@ class V15 extends Migration /** * Migrates a permission string * - * @param string $permission + * @param string $permission * @return string */ protected function migratePermission(string $permission): string @@ -735,7 +730,7 @@ class V15 extends Migration foreach ($this->documentsIterator($id) as $function) { $vars = $function->getAttribute('vars', []); - if (! is_array($vars)) { + if (!is_array($vars)) { continue; } @@ -756,7 +751,7 @@ class V15 extends Migration 'functionInternalId' => $function->getInternalId(), 'key' => (string) $key, 'value' => (string) $value, - 'search' => implode(' ', [$variableId, $key, $function->getId()]), + 'search' => implode(' ', [$variableId, $key, $function->getId()]) ]); $this->projectDB->createDocument('variables', $variable); } @@ -1228,7 +1223,7 @@ class V15 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) @@ -1479,14 +1474,14 @@ class V15 extends Migration $this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats:".$th->getMessage()); + Console::warning("Migrating steps from {$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); } } /** * Filter from the 'encrypt' filter. * - * @param string $value + * @param string $value * @return string|false */ protected function encryptFilter(string $value): string diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 761a274e0f..bee2236dfb 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -24,7 +24,7 @@ class V16 extends Migration ); } - Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -102,7 +102,7 @@ class V16 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) @@ -118,7 +118,7 @@ class V16 extends Migration * Set default authDuration */ $document->setAttribute('auths', array_merge($document->getAttribute('auths', []), [ - 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, + 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG ])); /** @@ -127,16 +127,16 @@ class V16 extends Migration $authProviders = $document->getAttribute('authProviders', []); foreach (Config::getParam('authProviders') as $provider => $value) { - if (! $value['enabled']) { + if (!$value['enabled']) { continue; } - if (($authProviders[$provider.'Appid'] ?? false) && ($authProviders[$provider.'Secret'] ?? false)) { - if (array_key_exists($provider.'Enabled', $authProviders)) { + if (($authProviders[$provider . 'Appid'] ?? false) && ($authProviders[$provider . 'Secret'] ?? false)) { + if (array_key_exists($provider . 'Enabled', $authProviders)) { continue; } - $authProviders[$provider.'Enabled'] = true; + $authProviders[$provider . 'Enabled'] = true; } } diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index 421c86bcc8..3f744d8069 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -23,7 +23,7 @@ class V17 extends Migration ); } - Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -33,11 +33,11 @@ class V17 extends Migration $this->forEachDocument([$this, 'fixDocument']); } + /** * Migrating all Bucket tables. * * @return void - * * @throws \Exception * @throws \PDOException */ @@ -234,7 +234,7 @@ class V17 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document + * @param \Utopia\Database\Document $document * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) @@ -250,15 +250,15 @@ class V17 extends Migration * Set default maxSessions */ $document->setAttribute('auths', array_merge($document->getAttribute('auths', []), [ - 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT, + 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT ])); break; case 'users': - /** + /** * Set hashOptions type */ $document->setAttribute('hashOptions', array_merge($document->getAttribute('hashOptions', []), [ - 'type' => $document->getAttribute('hash', Auth::DEFAULT_ALGO), + 'type' => $document->getAttribute('hash', Auth::DEFAULT_ALGO) ])); break; } diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index 2b3b98088d..839269f940 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -13,6 +13,7 @@ class V18 extends Migration { public function execute(): void { + /** * Disable SubQueries for Performance. */ @@ -24,7 +25,7 @@ class V18 extends Migration ); } - Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); $this->addDocumentSecurityToProject(); @@ -42,7 +43,6 @@ class V18 extends Migration * Migrate all Databases. * * @return void - * * @throws \Exception */ private function migrateDatabases(): void @@ -154,7 +154,7 @@ class V18 extends Migration /** * Fix run on each document * - * @param Document $document + * @param Document $document * @return Document */ protected function fixDocument(Document $document): Document diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index fe9bde6d29..39522aff0b 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -2,6 +2,8 @@ namespace Appwrite\Migration\Version; +use Appwrite\Auth\Auth; +use Utopia\Config\Config; use Appwrite\Migration\Migration; use Utopia\CLI\Console; use Utopia\Database\Database; @@ -11,6 +13,7 @@ class V19 extends Migration { public function execute(): void { + /** * Disable SubQueries for Performance. */ @@ -22,7 +25,7 @@ class V19 extends Migration ); } - Console::log('Migrating Project: '.$this->project->getAttribute('name').' ('.$this->project->getId().')'); + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); $this->alterPermissionIndex('_metadata'); @@ -45,7 +48,6 @@ class V19 extends Migration * Migrate all Databases. * * @return void - * * @throws \Exception */ private function migrateDatabases(): void @@ -97,7 +99,7 @@ class V19 extends Migration default: break; } - if (! in_array($id, ['files', 'collections'])) { + if (!in_array($id, ['files', 'collections'])) { $this->alterPermissionIndex($id); $this->alterUidType($id); } @@ -109,7 +111,7 @@ class V19 extends Migration /** * Fix run on each document * - * @param Document $document + * @param Document $document * @return Document */ protected function fixDocument(Document $document): Document @@ -161,7 +163,6 @@ class V19 extends Migration * Migrating all Bucket tables. * * @return void - * * @throws \Exception * @throws \PDOException */ diff --git a/src/Appwrite/Network/Validator/CNAME.php b/src/Appwrite/Network/Validator/CNAME.php index 3840322137..678a57cecd 100644 --- a/src/Appwrite/Network/Validator/CNAME.php +++ b/src/Appwrite/Network/Validator/CNAME.php @@ -12,7 +12,7 @@ class CNAME extends Validator protected $target; /** - * @param string $target + * @param string $target */ public function __construct($target) { @@ -30,12 +30,13 @@ class CNAME extends Validator /** * Check if CNAME record target value matches selected target * - * @param mixed $domain + * @param mixed $domain + * * @return bool */ public function isValid($domain): bool { - if (! is_string($domain)) { + if (!is_string($domain)) { return false; } @@ -45,7 +46,7 @@ class CNAME extends Validator return false; } - if (! $records) { + if (!$records) { return false; } diff --git a/src/Appwrite/Network/Validator/Email.php b/src/Appwrite/Network/Validator/Email.php index 232437aab7..efc1a5d5b3 100644 --- a/src/Appwrite/Network/Validator/Email.php +++ b/src/Appwrite/Network/Validator/Email.php @@ -8,6 +8,8 @@ use Utopia\Validator; * Email * * Validate that an variable is a valid email address + * + * @package Utopia\Validator */ class Email extends Validator { @@ -28,12 +30,12 @@ class Email extends Validator * * Validation will pass when $value is valid email address. * - * @param mixed $value + * @param mixed $value * @return bool */ public function isValid($value): bool { - if (! \filter_var($value, FILTER_VALIDATE_EMAIL)) { + if (!\filter_var($value, FILTER_VALIDATE_EMAIL)) { return false; } diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 78065c0e48..508961ab9e 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -2,55 +2,35 @@ namespace Appwrite\Network\Validator; -use Utopia\Validator; use Utopia\Validator\Hostname; +use Utopia\Validator; class Origin extends Validator { public const CLIENT_TYPE_UNKNOWN = 'unknown'; - public const CLIENT_TYPE_WEB = 'web'; - public const CLIENT_TYPE_FLUTTER_IOS = 'flutter-ios'; - public const CLIENT_TYPE_FLUTTER_ANDROID = 'flutter-android'; - public const CLIENT_TYPE_FLUTTER_MACOS = 'flutter-macos'; - public const CLIENT_TYPE_FLUTTER_WINDOWS = 'flutter-windows'; - public const CLIENT_TYPE_FLUTTER_LINUX = 'flutter-linux'; - public const CLIENT_TYPE_FLUTTER_WEB = 'flutter-web'; - public const CLIENT_TYPE_APPLE_IOS = 'apple-ios'; - public const CLIENT_TYPE_APPLE_MACOS = 'apple-macos'; - public const CLIENT_TYPE_APPLE_WATCHOS = 'apple-watchos'; - public const CLIENT_TYPE_APPLE_TVOS = 'apple-tvos'; - public const CLIENT_TYPE_ANDROID = 'android'; - public const CLIENT_TYPE_UNITY = 'unity'; + public const SCHEME_TYPE_HTTP = 'http'; - public const SCHEME_TYPE_HTTPS = 'https'; - public const SCHEME_TYPE_IOS = 'appwrite-ios'; - public const SCHEME_TYPE_MACOS = 'appwrite-macos'; - public const SCHEME_TYPE_WATCHOS = 'appwrite-watchos'; - public const SCHEME_TYPE_TVOS = 'appwrite-tvos'; - public const SCHEME_TYPE_ANDROID = 'appwrite-android'; - public const SCHEME_TYPE_WINDOWS = 'appwrite-windows'; - public const SCHEME_TYPE_LINUX = 'appwrite-linux'; /** @@ -85,7 +65,7 @@ class Origin extends Validator protected $host = ''; /** - * @param string $target + * @param string $target */ public function __construct($platforms) { @@ -112,7 +92,7 @@ class Origin extends Validator break; default: - // code... + # code... break; } } @@ -120,24 +100,25 @@ class Origin extends Validator public function getDescription(): string { - if (! \array_key_exists($this->client, $this->platforms)) { + if (!\array_key_exists($this->client, $this->platforms)) { return 'Unsupported platform'; } - return 'Invalid Origin. Register your new client ('.$this->host.') as a new ' - .$this->platforms[$this->client].' platform on your project console dashboard'; + return 'Invalid Origin. Register your new client (' . $this->host . ') as a new ' + . $this->platforms[$this->client] . ' platform on your project console dashboard'; } /** * Check if Origin has been allowed * for access to the API * - * @param mixed $origin + * @param mixed $origin + * * @return bool */ public function isValid($origin): bool { - if (! is_string($origin)) { + if (!is_string($origin)) { return false; } diff --git a/src/Appwrite/OpenSSL/OpenSSL.php b/src/Appwrite/OpenSSL/OpenSSL.php index 2eed67dd3e..1965a3c858 100644 --- a/src/Appwrite/OpenSSL/OpenSSL.php +++ b/src/Appwrite/OpenSSL/OpenSSL.php @@ -10,11 +10,12 @@ class OpenSSL * @param $data * @param $method * @param $key - * @param int $options - * @param string $iv - * @param null $tag - * @param string $aad - * @param int $tag_length + * @param int $options + * @param string $iv + * @param null $tag + * @param string $aad + * @param int $tag_length + * * @return string */ public static function encrypt($data, $method, $key, $options = 0, $iv = '', &$tag = null, $aad = '', $tag_length = 16) @@ -26,10 +27,11 @@ class OpenSSL * @param $data * @param $method * @param $password - * @param int $options - * @param string $iv - * @param string $tag - * @param string $aad + * @param int $options + * @param string $iv + * @param string $tag + * @param string $aad + * * @return string */ public static function decrypt($data, $method, $password, $options = 1, $iv = '', $tag = '', $aad = '') @@ -38,7 +40,8 @@ class OpenSSL } /** - * @param string $method + * @param string $method + * * @return int */ public static function cipherIVLength($method) @@ -48,7 +51,8 @@ class OpenSSL /** * @param $length - * @param null $crypto_strong + * @param null $crypto_strong + * * @return false|string */ public static function randomPseudoBytes($length, &$crypto_strong = null) diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index a24d72be2f..9e919127bf 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -2,25 +2,26 @@ namespace Appwrite\Platform\Services; -use Appwrite\Platform\Tasks\CalcTierStats; -use Appwrite\Platform\Tasks\CalcUsersStats; -use Appwrite\Platform\Tasks\ClearCardCache; +use Utopia\Platform\Service; use Appwrite\Platform\Tasks\Doctor; -use Appwrite\Platform\Tasks\Hamster; use Appwrite\Platform\Tasks\Install; use Appwrite\Platform\Tasks\Maintenance; use Appwrite\Platform\Tasks\Migrate; -use Appwrite\Platform\Tasks\PatchCreateMissingSchedules; -use Appwrite\Platform\Tasks\PatchDeleteProjectCollections; -use Appwrite\Platform\Tasks\PatchDeleteScheduleUpdatedAtAttribute; use Appwrite\Platform\Tasks\Schedule; +use Appwrite\Platform\Tasks\PatchCreateMissingSchedules; use Appwrite\Platform\Tasks\SDKs; use Appwrite\Platform\Tasks\Specs; use Appwrite\Platform\Tasks\SSL; +use Appwrite\Platform\Tasks\Hamster; +use Appwrite\Platform\Tasks\PatchDeleteScheduleUpdatedAtAttribute; +use Appwrite\Platform\Tasks\ClearCardCache; +use Appwrite\Platform\Tasks\Usage; use Appwrite\Platform\Tasks\Vars; use Appwrite\Platform\Tasks\Version; use Appwrite\Platform\Tasks\VolumeSync; -use Utopia\Platform\Service; +use Appwrite\Platform\Tasks\CalcUsersStats; +use Appwrite\Platform\Tasks\CalcTierStats; +use Appwrite\Platform\Tasks\PatchDeleteProjectCollections; class Tasks extends Service { @@ -45,6 +46,7 @@ class Tasks extends Service ->addAction(Specs::getName(), new Specs()) ->addAction(CalcUsersStats::getName(), new CalcUsersStats()) ->addAction(CalcTierStats::getName(), new CalcTierStats()) - ->addAction(PatchDeleteProjectCollections::getName(), new PatchDeleteProjectCollections()); + ->addAction(PatchDeleteProjectCollections::getName(), new PatchDeleteProjectCollections()) + ; } } diff --git a/src/Appwrite/Platform/Tasks/CalcTierStats.php b/src/Appwrite/Platform/Tasks/CalcTierStats.php index 0dc795cbcd..d660709940 100644 --- a/src/Appwrite/Platform/Tasks/CalcTierStats.php +++ b/src/Appwrite/Platform/Tasks/CalcTierStats.php @@ -4,15 +4,15 @@ namespace Appwrite\Platform\Tasks; use Exception; use League\Csv\CannotInsertRecord; -use League\Csv\Writer; -use PHPMailer\PHPMailer\PHPMailer; use Utopia\App; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Platform\Action; +use League\Csv\Writer; +use PHPMailer\PHPMailer\PHPMailer; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -44,13 +44,11 @@ class CalcTierStats extends Action ]; protected string $directory = '/usr/local'; - protected string $path; - protected string $date; private array $usageStats = [ - 'project.$all.network.requests' => 'Requests', + 'project.$all.network.requests' => 'Requests', 'project.$all.network.bandwidth' => 'Bandwidth', ]; @@ -62,6 +60,7 @@ class CalcTierStats extends Action public function __construct() { + $this ->desc('Get stats for projects') ->inject('pools') @@ -82,7 +81,7 @@ class CalcTierStats extends Action //docker compose exec -t appwrite calc-tier-stats Console::title('Cloud free tier stats calculation V1'); - Console::success(APP_NAME.' cloud free tier stats calculation has started'); + Console::success(APP_NAME . ' cloud free tier stats calculation has started'); /* Initialise new Utopia app */ $app = new App('UTC'); @@ -103,8 +102,9 @@ class CalcTierStats extends Action $limit = 30; $sum = 30; $offset = 0; - while (! empty($projects)) { + while (!empty($projects)) { foreach ($projects as $project) { + /** * Skip user projects with id 'console' */ @@ -123,18 +123,18 @@ class CalcTierStats extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase('appwrite'); - $dbForProject->setNamespace('_'.$project->getInternalId()); + $dbForProject->setNamespace('_' . $project->getInternalId()); /** Get Project ID */ $stats['Project ID'] = $project->getId(); - $stats['Organization ID'] = $project->getAttribute('teamId', null); + $stats['Organization ID'] = $project->getAttribute('teamId', null); /** Get Total Members */ $teamInternalId = $project->getAttribute('teamInternalId', null); if ($teamInternalId) { $stats['Organization Members'] = $dbForConsole->count('memberships', [ - Query::equal('teamInternalId', [$teamInternalId]), + Query::equal('teamInternalId', [$teamInternalId]) ]); } else { $stats['Organization Members'] = 0; @@ -195,7 +195,7 @@ class CalcTierStats extends Action }); foreach ($tmp as $key => $value) { - $stats[$metrics[$key]] = $value; + $stats[$metrics[$key]] = $value; } try { @@ -208,27 +208,27 @@ class CalcTierStats extends Action } try { - /** Get Api keys */ + /** Get Api keys */ $stats['Api keys'] = $dbForConsole->count('keys', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); } catch (\Throwable) { $stats['Api keys'] = 0; } try { - /** Get Webhooks */ + /** Get Webhooks */ $stats['Webhooks'] = $dbForConsole->count('webhooks', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); } catch (\Throwable) { $stats['Webhooks'] = 0; } try { - /** Get Platforms */ + /** Get Platforms */ $stats['Platforms'] = $dbForConsole->count('platforms', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); } catch (\Throwable) { $stats['Platforms'] = 0; @@ -242,26 +242,28 @@ class CalcTierStats extends Action try { $buckets = $dbForProject->find('buckets', []); foreach ($buckets as $bucket) { - $file = $dbForProject->findOne('bucket_'.$bucket->getInternalId(), [Query::orderDesc('sizeOriginal')]); + $file = $dbForProject->findOne('bucket_' . $bucket->getInternalId(), [Query::orderDesc('sizeOriginal'),]); if (empty($file)) { continue; } - $filesSum += $dbForProject->sum('bucket_'.$bucket->getInternalId(), 'sizeOriginal', [], 0); - $filesCount += $dbForProject->count('bucket_'.$bucket->getInternalId(), []); + $filesSum += $dbForProject->sum('bucket_' . $bucket->getInternalId(), 'sizeOriginal', [], 0); + $filesCount += $dbForProject->count('bucket_' . $bucket->getInternalId(), []); if ($file->getAttribute('sizeOriginal') > $maxFileSize) { $maxFileSize = $file->getAttribute('sizeOriginal'); } $counter++; } } catch (\Throwable) { + ; } $stats['Buckets'] = $counter; $stats['Files'] = $filesCount; $stats['Storage (bytes)'] = $filesSum; $stats['Max File Size (bytes)'] = $maxFileSize; + try { - /** Get Total Functions */ + /** Get Total Functions */ $stats['Databases'] = $dbForProject->count('databases', []); } catch (\Throwable) { $stats['Databases'] = 0; @@ -290,7 +292,7 @@ class CalcTierStats extends Action $csv->insertOne(array_values($stats)); } catch (\Throwable $th) { - Console::error('Failed on project ("'.$project->getId().'") version with error on File: '.$th->getFile().' line no: '.$th->getline().' with message: '.$th->getMessage()); + Console::error('Failed on project ("' . $project->getId() . '") version with error on File: ' . $th->getFile() . ' line no: ' . $th->getline() . ' with message: ' . $th->getMessage()); } finally { $pools ->get($db) @@ -309,7 +311,7 @@ class CalcTierStats extends Action $count = $count + $sum; } - Console::log('Iterated through '.$count - 1 .'/'.$totalProjects.' projects...'); + Console::log('Iterated through ' . $count - 1 . '/' . $totalProjects . ' projects...'); $pools ->get('console') @@ -339,7 +341,7 @@ class CalcTierStats extends Action /** Content */ $mail->Subject = "Cloud Report for {$this->date}"; - $mail->Body = 'Please find the daily cloud report atttached'; + $mail->Body = "Please find the daily cloud report atttached"; $mail->send(); Console::success('Email has been sent!'); } catch (Exception $e) { diff --git a/src/Appwrite/Platform/Tasks/CalcUsersStats.php b/src/Appwrite/Platform/Tasks/CalcUsersStats.php index 67fcc1a5c5..6310fe17b4 100644 --- a/src/Appwrite/Platform/Tasks/CalcUsersStats.php +++ b/src/Appwrite/Platform/Tasks/CalcUsersStats.php @@ -3,14 +3,14 @@ namespace Appwrite\Platform\Tasks; use Exception; -use League\Csv\Writer; -use PHPMailer\PHPMailer\PHPMailer; use Utopia\App; +use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Query; -use Utopia\Platform\Action; +use League\Csv\Writer; +use PHPMailer\PHPMailer\PHPMailer; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -21,13 +21,11 @@ class CalcUsersStats extends Action 'Project Name', 'Team ID', 'Team name', - 'Users', + 'Users' ]; protected string $directory = '/usr/local'; - protected string $path; - protected string $date; public static function getName(): string @@ -37,6 +35,7 @@ class CalcUsersStats extends Action public function __construct() { + $this ->desc('Get stats for projects') ->inject('pools') @@ -53,7 +52,7 @@ class CalcUsersStats extends Action //docker compose exec -t appwrite calc-users-stats Console::title('Cloud Users calculation V1'); - Console::success(APP_NAME.' cloud Users calculation has started'); + Console::success(APP_NAME . ' cloud Users calculation has started'); /* Initialise new Utopia app */ $app = new App('UTC'); @@ -74,8 +73,9 @@ class CalcUsersStats extends Action $limit = 30; $sum = 30; $offset = 0; - while (! empty($projects)) { + while (!empty($projects)) { foreach ($projects as $project) { + /** * Skip user projects with id 'console' */ @@ -94,7 +94,7 @@ class CalcUsersStats extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase('appwrite'); - $dbForProject->setNamespace('_'.$project->getInternalId()); + $dbForProject->setNamespace('_' . $project->getInternalId()); /** Get Project ID */ $stats['Project ID'] = $project->getId(); @@ -102,6 +102,7 @@ class CalcUsersStats extends Action /** Get Project Name */ $stats['Project Name'] = $project->getAttribute('name'); + /** Get Team Name and Id */ $teamId = $project->getAttribute('teamId', null); $teamName = null; @@ -110,7 +111,7 @@ class CalcUsersStats extends Action $teamName = $team->getAttribute('name'); } - $stats['Team ID'] = $teamId; + $stats['Team ID'] = $teamId; $stats['Team name'] = $teamName; /** Get Total Users */ @@ -118,7 +119,7 @@ class CalcUsersStats extends Action $csv->insertOne(array_values($stats)); } catch (\Throwable $th) { - Console::error('Failed to update project ("'.$project->getId().'") version with error: '.$th->getMessage()); + Console::error('Failed to update project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); } finally { $pools ->get($db) @@ -136,7 +137,7 @@ class CalcUsersStats extends Action $offset = $offset + $limit; $count = $count + $sum; } - Console::log('Iterated through '.$count - 1 .'/'.$totalProjects.' projects...'); + Console::log('Iterated through ' . $count - 1 . '/' . $totalProjects . ' projects...'); $pools ->get('console') ->reclaim(); @@ -165,7 +166,7 @@ class CalcUsersStats extends Action /** Content */ $mail->Subject = "Cloud Report for {$this->date}"; - $mail->Body = 'Please find the daily cloud report atttached'; + $mail->Body = "Please find the daily cloud report atttached"; $mail->send(); Console::success('Email has been sent!'); } catch (Exception $e) { diff --git a/src/Appwrite/Platform/Tasks/ClearCardCache.php b/src/Appwrite/Platform/Tasks/ClearCardCache.php index 59499b6888..d3153b995c 100644 --- a/src/Appwrite/Platform/Tasks/ClearCardCache.php +++ b/src/Appwrite/Platform/Tasks/ClearCardCache.php @@ -4,12 +4,12 @@ namespace Appwrite\Platform\Tasks; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; +use Utopia\Platform\Action; use Utopia\CLI\Console; -use Utopia\Database\Database; use Utopia\Database\Query; +use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; class ClearCardCache extends Action { @@ -33,12 +33,12 @@ class ClearCardCache extends Action Authorization::setDefaultStatus(false); Console::title('ClearCardCache V1'); - Console::success(APP_NAME.' ClearCardCache v1 has started'); - $resources = ['card/'.$userId, 'card-back/'.$userId, 'card-og/'.$userId]; + Console::success(APP_NAME . ' ClearCardCache v1 has started'); + $resources = ['card/' . $userId, 'card-back/' . $userId, 'card-og/' . $userId]; $caches = Authorization::skip(fn () => $dbForConsole->find('cache', [ Query::equal('resource', $resources), - Query::limit(100), + Query::limit(100) ])); $count = \count($caches); @@ -49,7 +49,7 @@ class ClearCardCache extends Action $key = $cache->getId(); $cacheFolder = new Cache( - new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-console') + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-console') ); $cacheFolder->purge($key); @@ -57,6 +57,6 @@ class ClearCardCache extends Action Authorization::skip(fn () => $dbForConsole->deleteDocument('cache', $cache->getId())); } - Console::success(APP_NAME.' ClearCardCache v1 has finished'); + Console::success(APP_NAME . ' ClearCardCache v1 has finished'); } } diff --git a/src/Appwrite/Platform/Tasks/Doctor.php b/src/Appwrite/Platform/Tasks/Doctor.php index 8b37e578f4..9a6d6a2847 100644 --- a/src/Appwrite/Platform/Tasks/Doctor.php +++ b/src/Appwrite/Platform/Tasks/Doctor.php @@ -2,16 +2,16 @@ namespace Appwrite\Platform\Tasks; -use Appwrite\ClamAV\Network; use Utopia\App; use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Domains\Domain; +use Appwrite\ClamAV\Network; use Utopia\Logger\Logger; -use Utopia\Platform\Action; -use Utopia\Registry\Registry; use Utopia\Storage\Device\Local; use Utopia\Storage\Storage; +use Utopia\Config\Config; +use Utopia\Domains\Domain; +use Utopia\Platform\Action; +use Utopia\Registry\Registry; class Doctor extends Action { @@ -35,24 +35,24 @@ class Doctor extends Action / \ ) __/ ) __/\ /\ / ) / )( )( ) _) _ )(( O ) \_/\_/(__) (__) (_/\_)(__\_)(__) (__) (____)(_)(__)\__/ "); - Console::log("\n".'👩‍⚕️ Running '.APP_NAME.' Doctor for version '.App::getEnv('_APP_VERSION', 'UNKNOWN').' ...'."\n"); + Console::log("\n" . '👩‍⚕️ Running ' . APP_NAME . ' Doctor for version ' . App::getEnv('_APP_VERSION', 'UNKNOWN') . ' ...' . "\n"); Console::log('[Settings]'); $domain = new Domain(App::getEnv('_APP_DOMAIN')); - if (! $domain->isKnown() || $domain->isTest()) { - Console::log('🔴 Hostname has no public suffix ('.$domain->get().')'); + if (!$domain->isKnown() || $domain->isTest()) { + Console::log('🔴 Hostname has no public suffix (' . $domain->get() . ')'); } else { - Console::log('🟢 Hostname has a public suffix ('.$domain->get().')'); + Console::log('🟢 Hostname has a public suffix (' . $domain->get() . ')'); } $domain = new Domain(App::getEnv('_APP_DOMAIN_TARGET')); - if (! $domain->isKnown() || $domain->isTest()) { - Console::log('🔴 CNAME target has no public suffix ('.$domain->get().')'); + if (!$domain->isKnown() || $domain->isTest()) { + Console::log('🔴 CNAME target has no public suffix (' . $domain->get() . ')'); } else { - Console::log('🟢 CNAME target has a public suffix ('.$domain->get().')'); + Console::log('🟢 CNAME target has a public suffix (' . $domain->get() . ')'); } if (App::getEnv('_APP_OPENSSL_KEY_V1') === 'your-secret-key' || empty(App::getEnv('_APP_OPENSSL_KEY_V1'))) { @@ -96,21 +96,22 @@ class Doctor extends Action $providerName = App::getEnv('_APP_LOGGING_PROVIDER', ''); $providerConfig = App::getEnv('_APP_LOGGING_CONFIG', ''); - if (empty($providerName) || empty($providerConfig) || ! Logger::hasProvider($providerName)) { + if (empty($providerName) || empty($providerConfig) || !Logger::hasProvider($providerName)) { Console::log('🔴 Logging adapter is disabled'); } else { - Console::log('🟢 Logging adapter is enabled ('.$providerName.')'); + Console::log('🟢 Logging adapter is enabled (' . $providerName . ')'); } \sleep(0.2); try { - Console::log("\n".'[Connectivity]'); + Console::log("\n" . '[Connectivity]'); } catch (\Throwable $th) { //throw $th; } $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ + $configs = [ 'Console.DB' => Config::getParam('pools-console'), 'Projects.DB' => Config::getParam('pools-database'), @@ -122,12 +123,12 @@ class Doctor extends Action $adapter = $pools->get($database)->pop()->getResource(); if ($adapter->ping()) { - Console::success('🟢 '.str_pad("{$key}({$database})", 50, '.').'connected'); + Console::success('🟢 ' . str_pad("{$key}({$database})", 50, '.') . 'connected'); } else { - Console::error('🔴 '.str_pad("{$key}({$database})", 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("{$key}({$database})", 47, '.') . 'disconnected'); } } catch (\Throwable $th) { - Console::error('🔴 '.str_pad("{$key}.({$database})", 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("{$key}.({$database})", 47, '.') . 'disconnected'); } } } @@ -145,12 +146,12 @@ class Doctor extends Action $adapter = $pools->get($pool)->pop()->getResource(); if ($adapter->ping()) { - Console::success('🟢 '.str_pad("{$key}({$pool})", 50, '.').'connected'); + Console::success('🟢 ' . str_pad("{$key}({$pool})", 50, '.') . 'connected'); } else { - Console::error('🔴 '.str_pad("{$key}({$pool})", 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("{$key}({$pool})", 47, '.') . 'disconnected'); } } catch (\Throwable $th) { - Console::error('🔴 '.str_pad("{$key}({$pool})", 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("{$key}({$pool})", 47, '.') . 'disconnected'); } } } @@ -163,12 +164,12 @@ class Doctor extends Action ); if ((@$antivirus->ping())) { - Console::success('🟢 '.str_pad('Antivirus', 50, '.').'connected'); + Console::success('🟢 ' . str_pad("Antivirus", 50, '.') . 'connected'); } else { - Console::error('🔴 '.str_pad('Antivirus', 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("Antivirus", 47, '.') . 'disconnected'); } } catch (\Throwable $th) { - Console::error('🔴 '.str_pad('Antivirus', 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("Antivirus", 47, '.') . 'disconnected'); } } @@ -181,9 +182,9 @@ class Doctor extends Action $mail->AltBody = 'Hello World'; $mail->send(); - Console::success('🟢 '.str_pad('SMTP', 50, '.').'connected'); + Console::success('🟢 ' . str_pad("SMTP", 50, '.') . 'connected'); } catch (\Throwable $th) { - Console::error('🔴 '.str_pad('SMTP', 47, '.').'disconnected'); + Console::error('🔴 ' . str_pad("SMTP", 47, '.') . 'disconnected'); } \sleep(0.2); @@ -193,24 +194,24 @@ class Doctor extends Action foreach ( [ - 'Uploads' => APP_STORAGE_UPLOADS, - 'Cache' => APP_STORAGE_CACHE, - 'Config' => APP_STORAGE_CONFIG, - 'Certs' => APP_STORAGE_CERTIFICATES, + 'Uploads' => APP_STORAGE_UPLOADS, + 'Cache' => APP_STORAGE_CACHE, + 'Config' => APP_STORAGE_CONFIG, + 'Certs' => APP_STORAGE_CERTIFICATES ] as $key => $volume ) { $device = new Local($volume); if (\is_readable($device->getRoot())) { - Console::success('🟢 '.$key.' Volume is readable'); + Console::success('🟢 ' . $key . ' Volume is readable'); } else { - Console::error('🔴 '.$key.' Volume is unreadable'); + Console::error('🔴 ' . $key . ' Volume is unreadable'); } if (\is_writable($device->getRoot())) { - Console::success('🟢 '.$key.' Volume is writeable'); + Console::success('🟢 ' . $key . ' Volume is writeable'); } else { - Console::error('🔴 '.$key.' Volume is unwriteable'); + Console::error('🔴 ' . $key . ' Volume is unwriteable'); } } @@ -221,10 +222,10 @@ class Doctor extends Action foreach ( [ - 'Uploads' => APP_STORAGE_UPLOADS, - 'Cache' => APP_STORAGE_CACHE, - 'Config' => APP_STORAGE_CONFIG, - 'Certs' => APP_STORAGE_CERTIFICATES, + 'Uploads' => APP_STORAGE_UPLOADS, + 'Cache' => APP_STORAGE_CACHE, + 'Config' => APP_STORAGE_CONFIG, + 'Certs' => APP_STORAGE_CERTIFICATES ] as $key => $volume ) { $device = new Local($volume); @@ -232,32 +233,32 @@ class Doctor extends Action $percentage = (($device->getPartitionTotalSpace() - $device->getPartitionFreeSpace()) / $device->getPartitionTotalSpace()) * 100; - $message = $key.' Volume has '.Storage::human($device->getPartitionFreeSpace()).' free space ('.\round($percentage, 2).'% used)'; + $message = $key . ' Volume has ' . Storage::human($device->getPartitionFreeSpace()) . ' free space (' . \round($percentage, 2) . '% used)'; if ($percentage < 80) { - Console::success('🟢 '.$message); + Console::success('🟢 ' . $message); } else { - Console::error('🔴 '.$message); + Console::error('🔴 ' . $message); } } try { if (App::isProduction()) { Console::log(''); - $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost').'/v1/health/version'), true); + $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost') . '/v1/health/version'), true); if ($version && isset($version['version'])) { if (\version_compare($version['version'], App::getEnv('_APP_VERSION', 'UNKNOWN')) === 0) { - Console::info('You are running the latest version of '.APP_NAME.'! 🥳'); + Console::info('You are running the latest version of ' . APP_NAME . '! 🥳'); } else { - Console::info('A new version ('.$version['version'].') is available! 🥳'."\n"); + Console::info('A new version (' . $version['version'] . ') is available! 🥳' . "\n"); } } else { - Console::error('Failed to check for a newer version'."\n"); + Console::error('Failed to check for a newer version' . "\n"); } } } catch (\Throwable $th) { - Console::error('Failed to check for a newer version'."\n"); + Console::error('Failed to check for a newer version' . "\n"); } } } diff --git a/src/Appwrite/Platform/Tasks/Hamster.php b/src/Appwrite/Platform/Tasks/Hamster.php index 85545f1a19..5b04c338eb 100644 --- a/src/Appwrite/Platform/Tasks/Hamster.php +++ b/src/Appwrite/Platform/Tasks/Hamster.php @@ -4,17 +4,17 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Network\Validator\Origin; use Exception; -use Utopia\Analytics\Adapter\Mixpanel; -use Utopia\Analytics\Event; use Utopia\App; +use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; -use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Platform\Action; +use Utopia\Analytics\Adapter\Mixpanel; +use Utopia\Analytics\Event; +use Utopia\Config\Config; +use Utopia\Database\Document; use Utopia\Pools\Group; class Hamster extends Action @@ -67,8 +67,7 @@ class Hamster extends Action * Skip user projects with id 'console' */ if ($project->getId() === 'console') { - Console::info('Skipping project console'); - + Console::info("Skipping project console"); return; } @@ -83,7 +82,7 @@ class Hamster extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase('appwrite'); - $dbForProject->setNamespace('_'.$project->getInternalId()); + $dbForProject->setNamespace('_' . $project->getInternalId()); $statsPerProject = []; @@ -102,7 +101,7 @@ class Hamster extends Action $statsPerProject['custom_functions'] = $dbForProject->count('functions', [], APP_LIMIT_COUNT); foreach (\array_keys(Config::getParam('runtimes')) as $runtime) { - $statsPerProject['custom_functions_'.$runtime] = $dbForProject->count('functions', [ + $statsPerProject['custom_functions_' . $runtime] = $dbForProject->count('functions', [ Query::equal('runtime', [$runtime]), ], APP_LIMIT_COUNT); } @@ -117,7 +116,7 @@ class Hamster extends Action $teamInternalId = $project->getAttribute('teamInternalId', null); if ($teamInternalId) { $statsPerProject['custom_organization_members'] = $dbForConsole->count('memberships', [ - Query::equal('teamInternalId', [$teamInternalId]), + Query::equal('teamInternalId', [$teamInternalId]) ], APP_LIMIT_COUNT); } else { $statsPerProject['custom_organization_members'] = 0; @@ -129,8 +128,8 @@ class Hamster extends Action Query::equal('teamInternalId', [$teamInternalId]), ]); - if (! $membership || $membership->isEmpty()) { - throw new Exception('Membership not found. Skipping project : '.$project->getId()); + if (!$membership || $membership->isEmpty()) { + throw new Exception('Membership not found. Skipping project : ' . $project->getId()); } $userInternalId = $membership->getAttribute('userInternalId', null); @@ -147,42 +146,42 @@ class Hamster extends Action /** Get Domains */ $statsPerProject['custom_domains'] = $dbForConsole->count('domains', [ Query::equal('projectInternalId', [$project->getInternalId()]), - Query::limit(APP_LIMIT_COUNT), + Query::limit(APP_LIMIT_COUNT) ]); /** Get Platforms */ $platforms = $dbForConsole->find('platforms', [ Query::equal('projectInternalId', [$project->getInternalId()]), - Query::limit(APP_LIMIT_COUNT), + Query::limit(APP_LIMIT_COUNT) ]); - $statsPerProject['custom_platforms_web'] = count(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_web'] = sizeof(array_filter($platforms, function ($platform) { return $platform['type'] === 'web'; })); - $statsPerProject['custom_platforms_android'] = count(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_android'] = sizeof(array_filter($platforms, function ($platform) { return $platform['type'] === 'android'; })); - $statsPerProject['custom_platforms_apple'] = count(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_apple'] = sizeof(array_filter($platforms, function ($platform) { return str_contains($platform['type'], 'apple'); })); - $statsPerProject['custom_platforms_flutter'] = count(array_filter($platforms, function ($platform) { + $statsPerProject['custom_platforms_flutter'] = sizeof(array_filter($platforms, function ($platform) { return str_contains($platform['type'], 'flutter'); })); $flutterPlatforms = [Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_FLUTTER_LINUX]; foreach ($flutterPlatforms as $flutterPlatform) { - $statsPerProject['custom_platforms_'.$flutterPlatform] = count(array_filter($platforms, function ($platform) use ($flutterPlatform) { + $statsPerProject['custom_platforms_' . $flutterPlatform] = sizeof(array_filter($platforms, function ($platform) use ($flutterPlatform) { return $platform['type'] === $flutterPlatform; })); } $statsPerProject['custom_platforms_api_keys'] = $dbForConsole->count('keys', [ Query::equal('projectInternalId', [$project->getInternalId()]), - Query::limit(APP_LIMIT_COUNT), + Query::limit(APP_LIMIT_COUNT) ]); /** Get Usage $statsPerProject */ @@ -210,17 +209,17 @@ class Hamster extends Action Query::orderDesc('time'), ]); - $statsPerProject[$key.'_'.$periodKey] = []; + $statsPerProject[$key . '_' . $periodKey] = []; foreach ($requestDocs as $requestDoc) { - $statsPerProject[$key.'_'.$periodKey][] = [ + $statsPerProject[$key . '_' . $periodKey][] = [ 'value' => $requestDoc->getAttribute('value'), 'date' => $requestDoc->getAttribute('time'), ]; } - $statsPerProject[$key.'_'.$periodKey] = array_reverse($statsPerProject[$key.'_'.$periodKey]); + $statsPerProject[$key . '_' . $periodKey] = array_reverse($statsPerProject[$key . '_' . $periodKey]); // Calculate aggregate of each metric - $statsPerProject[$key.'_'.$periodKey] = array_sum(array_column($statsPerProject[$key.'_'.$periodKey], 'value')); + $statsPerProject[$key . '_' . $periodKey] = array_sum(array_column($statsPerProject[$key . '_' . $periodKey], 'value')); } } }); @@ -229,11 +228,11 @@ class Hamster extends Action /** Send data to mixpanel */ $res = $this->mixpanel->createProfile($statsPerProject['email'], '', [ 'name' => $statsPerProject['name'], - 'email' => $statsPerProject['email'], + 'email' => $statsPerProject['email'] ]); - if (! $res) { - Console::error('Failed to create user profile for project: '.$project->getId()); + if (!$res) { + Console::error('Failed to create user profile for project: ' . $project->getId()); } $event = new Event(); @@ -241,12 +240,12 @@ class Hamster extends Action ->setName('Project Daily Usage') ->setProps($statsPerProject); $res = $this->mixpanel->createEvent($event); - if (! $res) { - Console::error('Failed to create event for project: '.$project->getId()); + if (!$res) { + Console::error('Failed to create event for project: ' . $project->getId()); } } } catch (Exception $e) { - Console::error('Failed to send stats for project: '.$project->getId()); + Console::error('Failed to send stats for project: ' . $project->getId()); Console::error($e->getMessage()); } finally { $pools @@ -258,8 +257,9 @@ class Hamster extends Action public function action(Group $pools, Cache $cache, Database $dbForConsole): void { + Console::title('Cloud Hamster V1'); - Console::success(APP_NAME.' cloud hamster process has started'); + Console::success(APP_NAME . ' cloud hamster process has started'); $sleep = (int) App::getEnv('_APP_HAMSTER_INTERVAL', '30'); // 30 seconds (by default) @@ -278,7 +278,7 @@ class Hamster extends Action $delay = $next->getTimestamp() - $now->getTimestamp(); } - Console::log('['.$now->format('Y-m-d H:i:s.v').'] Delaying for '.$delay.' setting loop to ['.$next->format('Y-m-d H:i:s.v').']'); + Console::log('[' . $now->format("Y-m-d H:i:s.v") . '] Delaying for ' . $delay . ' setting loop to [' . $next->format("Y-m-d H:i:s.v") . ']'); Console::loop(function () use ($pools, $cache, $dbForConsole, $sleep) { $now = date('d-m-Y H:i:s', time()); @@ -325,12 +325,12 @@ class Hamster extends Action $results = $dbForConsole->find($collection, \array_merge([ Query::limit($limit), - Query::offset($count), + Query::offset($count) ])); $sum = count($results); - Console::log('Processing chunk #'.$chunk.'. Found '.$sum.' documents'); + Console::log('Processing chunk #' . $chunk . '. Found ' . $sum . ' documents'); foreach ($results as $document) { call_user_func($callback, $dbForConsole, $document); @@ -340,11 +340,12 @@ class Hamster extends Action $executionEnd = \microtime(true); - Console::log("Processed {$count} document by group in ".($executionEnd - $executionStart).' seconds'); + Console::log("Processed {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); } protected function getStatsPerOrganization(Database $dbForConsole) { + $this->calculateByGroup('teams', $dbForConsole, function (Database $dbForConsole, Document $document) { try { $statsPerOrganization = []; @@ -357,8 +358,8 @@ class Hamster extends Action Query::equal('teamInternalId', [$document->getInternalId()]), ]); - if (! $membership || $membership->isEmpty()) { - throw new Exception('Membership not found. Skipping organization : '.$document->getId()); + if (!$membership || $membership->isEmpty()) { + throw new Exception('Membership not found. Skipping organization : ' . $document->getId()); } $userInternalId = $membership->getAttribute('userInternalId', null); @@ -379,11 +380,11 @@ class Hamster extends Action /** Number of projects in this organization */ $statsPerOrganization['projects'] = $dbForConsole->count('projects', [ Query::equal('teamId', [$document->getId()]), - Query::limit(APP_LIMIT_COUNT), + Query::limit(APP_LIMIT_COUNT) ]); - if (! isset($statsPerOrganization['email'])) { - throw new Exception('Email not found. Skipping organization : '.$document->getId()); + if (!isset($statsPerOrganization['email'])) { + throw new Exception('Email not found. Skipping organization : ' . $document->getId()); } $event = new Event(); @@ -391,8 +392,8 @@ class Hamster extends Action ->setName('Organization Daily Usage') ->setProps($statsPerOrganization); $res = $this->mixpanel->createEvent($event); - if (! $res) { - throw new Exception('Failed to create event for organization : '.$document->getId()); + if (!$res) { + throw new Exception('Failed to create event for organization : ' . $document->getId()); } } catch (Exception $e) { Console::error($e->getMessage()); @@ -418,11 +419,11 @@ class Hamster extends Action /** Number of teams this user is a part of */ $statsPerUser['memberships'] = $dbForConsole->count('memberships', [ Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_COUNT), + Query::limit(APP_LIMIT_COUNT) ]); - if (! isset($statsPerUser['email'])) { - throw new Exception('User has no email: '.$document->getId()); + if (!isset($statsPerUser['email'])) { + throw new Exception('User has no email: ' . $document->getId()); } /** Send data to mixpanel */ @@ -432,8 +433,8 @@ class Hamster extends Action ->setProps($statsPerUser); $res = $this->mixpanel->createEvent($event); - if (! $res) { - throw new Exception('Failed to create user profile for user: '.$document->getId()); + if (!$res) { + throw new Exception('Failed to create user profile for user: ' . $document->getId()); } } catch (Exception $e) { Console::error($e->getMessage()); diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index 9c25320b6d..be12eadf62 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -9,8 +9,8 @@ use Appwrite\Utopia\View; use Utopia\Analytics\GoogleAnalytics; use Utopia\CLI\Console; use Utopia\Config\Config; -use Utopia\Platform\Action; use Utopia\Validator\Text; +use Utopia\Platform\Action; class Install extends Action { @@ -70,19 +70,19 @@ class Install extends Action Console::success('Starting Appwrite installation...'); // Create directory with write permissions - if (null !== $path && ! \file_exists(\dirname($path))) { - if (! @\mkdir(\dirname($path), 0755, true)) { - Console::error('Can\'t create directory '.\dirname($path)); + if (null !== $path && !\file_exists(\dirname($path))) { + if (!@\mkdir(\dirname($path), 0755, true)) { + Console::error('Can\'t create directory ' . \dirname($path)); Console::exit(1); } } - $data = @file_get_contents($path.'/docker-compose.yml'); + $data = @file_get_contents($path . '/docker-compose.yml'); if ($data !== false) { $time = \time(); - Console::info('Compose file found, creating backup: docker-compose.yml.'.$time.'.backup'); - file_put_contents($path.'/docker-compose.yml.'.$time.'.backup', $data); + Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); + file_put_contents($path . '/docker-compose.yml.' . $time . '.backup', $data); $compose = new Compose($data); $appwrite = $compose->getService('appwrite'); $oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null; @@ -91,14 +91,14 @@ class Install extends Action } catch (\Throwable $th) { $ports = [ $defaultHTTPPort => $defaultHTTPPort, - $defaultHTTPSPort => $defaultHTTPSPort, + $defaultHTTPSPort => $defaultHTTPSPort ]; Console::warning('Traefik not found. Falling back to default ports.'); } if ($oldVersion) { foreach ($compose->getServices() as $service) { // Fetch all env vars from previous compose file - if (! $service) { + if (!$service) { continue; } @@ -116,11 +116,11 @@ class Install extends Action } } - $data = @file_get_contents($path.'/.env'); + $data = @file_get_contents($path . '/.env'); if ($data !== false) { // Fetch all env vars from previous .env file - Console::info('Env file found, creating backup: .env.'.$time.'.backup'); - file_put_contents($path.'/.env.'.$time.'.backup', $data); + Console::info('Env file found, creating backup: .env.' . $time . '.backup'); + file_put_contents($path . '/.env.' . $time . '.backup', $data); $env = new Env($data); foreach ($env->list() as $key => $value) { @@ -148,44 +148,40 @@ class Install extends Action } if (empty($httpPort)) { - $httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')'); + $httpPort = Console::confirm('Choose your server HTTP port: (default: ' . $defaultHTTPPort . ')'); $httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort; } if (empty($httpsPort)) { - $httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')'); + $httpsPort = Console::confirm('Choose your server HTTPS port: (default: ' . $defaultHTTPSPort . ')'); $httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort; } $input = []; foreach ($vars as $var) { - if (! empty($var['filter']) && ($interactive !== 'Y' || ! Console::isInteractive())) { + if (!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) { if ($data && $var['default'] !== null) { $input[$var['name']] = $var['default']; - continue; } if ($var['filter'] === 'token') { $input[$var['name']] = Auth::tokenGenerator(); - continue; } if ($var['filter'] === 'password') { $input[$var['name']] = Auth::passwordGenerator(); - continue; } } - if (! $var['required'] || ! Console::isInteractive() || $interactive !== 'Y') { + if (!$var['required'] || !Console::isInteractive() || $interactive !== 'Y') { $input[$var['name']] = $var['default']; - continue; } - $input[$var['name']] = Console::confirm($var['question'].' (default: \''.$var['default'].'\')'); + $input[$var['name']] = Console::confirm($var['question'] . ' (default: \'' . $var['default'] . '\')'); if (empty($input[$var['name']])) { $input[$var['name']] = $var['default']; @@ -195,36 +191,38 @@ class Install extends Action if ($input[$var['name']] !== 'localhost') { Console::warning("\nIf you haven't already done so, set the following record for {$input[$var['name']]} on your DNS provider:\n"); $mask = "%-15.15s %-10.10s %-30.30s\n"; - printf($mask, 'Type', 'Name', 'Value'); - printf($mask, 'A or AAAA', '@', ''); + printf($mask, "Type", "Name", "Value"); + printf($mask, "A or AAAA", "@", ""); Console::warning("\nUse 'AAAA' if you're using an IPv6 address and 'A' if you're using an IPv4 address.\n"); } } } - $templateForCompose = new View(__DIR__.'/../views/install/compose.phtml'); - $templateForEnv = new View(__DIR__.'/../views/install/env.phtml'); + $templateForCompose = new View(__DIR__ . '/../views/install/compose.phtml'); + $templateForEnv = new View(__DIR__ . '/../views/install/env.phtml'); $templateForCompose ->setParam('httpPort', $httpPort) ->setParam('httpsPort', $httpsPort) ->setParam('version', APP_VERSION_STABLE) ->setParam('organization', $organization) - ->setParam('image', $image); + ->setParam('image', $image) + ; $templateForEnv - ->setParam('vars', $input); + ->setParam('vars', $input) + ; - if (! file_put_contents($path.'/docker-compose.yml', $templateForCompose->render(false))) { + if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::error($message); Console::exit(1); } - if (! file_put_contents($path.'/.env', $templateForEnv->render(false))) { + if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::error($message); Console::exit(1); } @@ -235,23 +233,23 @@ class Install extends Action foreach ($input as $key => $value) { if ($value) { - $env .= $key.'='.\escapeshellarg($value).' '; + $env .= $key . '=' . \escapeshellarg($value) . ' '; } } - Console::log('Running "docker compose up -d --remove-orphans --renew-anon-volumes"'); + Console::log("Running \"docker compose up -d --remove-orphans --renew-anon-volumes\""); $exit = Console::execute("${env} docker compose --project-directory {$path} up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr); if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::error($message); Console::error($stderr); Console::exit($exit); } else { $message = 'Appwrite installed successfully'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::success($message); } } diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index df93feb4af..0739923e34 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -2,13 +2,14 @@ namespace Appwrite\Platform\Tasks; +use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\DateTime; use Utopia\Database\Query; use Utopia\Platform\Action; @@ -30,7 +31,7 @@ class Maintenance extends Action public function action(Database $dbForConsole): void { Console::title('Maintenance V1'); - Console::success(APP_NAME.' maintenance process v1 has started'); + Console::success(APP_NAME . ' maintenance process v1 has started'); function notifyDeleteExecutionLogs(int $interval) { @@ -84,19 +85,20 @@ class Maintenance extends Action $time = DateTime::now(); $certificates = $dbForConsole->find('certificates', [ - Query::lessThan('attempts', 5), // Maximum 5 attempts - Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) - Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains) + Query::lessThan('attempts', 5), // Maximum 5 attempts + Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) + Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains) ]); + if (\count($certificates) > 0) { - Console::info("[{$time}] Found ".\count($certificates).' certificates for renewal, scheduling jobs.'); + Console::info("[{$time}] Found " . \count($certificates) . " certificates for renewal, scheduling jobs."); $event = new Certificate(); foreach ($certificates as $certificate) { $event ->setDomain(new Document([ - 'domain' => $certificate->getAttribute('domain'), + 'domain' => $certificate->getAttribute('domain') ])) ->trigger(); } @@ -107,6 +109,7 @@ class Maintenance extends Action function notifyDeleteCache($interval) { + (new Delete()) ->setType(DELETE_TYPE_CACHE_BY_TIMESTAMP) ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) @@ -115,6 +118,7 @@ class Maintenance extends Action function notifyDeleteSchedules($interval) { + (new Delete()) ->setType(DELETE_TYPE_SCHEDULES) ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index b4112f8d3f..90b4234109 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -2,14 +2,14 @@ namespace Appwrite\Platform\Tasks; +use Utopia\Platform\Action; +use Utopia\CLI\Console; use Appwrite\Migration\Migration; use Utopia\App; -use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Cache; -use Utopia\CLI\Console; +use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Platform\Action; use Utopia\Registry\Registry; use Utopia\Validator\Text; @@ -35,23 +35,22 @@ class Migrate extends Action try { $redis->del($redis->keys("cache-_{$project->getInternalId()}:*")); } catch (\Throwable $th) { - Console::error('Failed to clear project ("'.$project->getId().'") cache with error: '.$th->getMessage()); + Console::error('Failed to clear project ("' . $project->getId() . '") cache with error: ' . $th->getMessage()); } } public function action(string $version, Registry $register) { Authorization::disable(); - if (! array_key_exists($version, Migration::$versions)) { + if (!array_key_exists($version, Migration::$versions)) { Console::error("Version {$version} not found."); Console::exit(1); - return; } $app = new App('UTC'); - Console::success('Starting Data Migration to version '.$version); + Console::success('Starting Data Migration to version ' . $version); $dbPool = $register->get('dbPool', true); $redis = $register->get('cache', true); @@ -79,10 +78,10 @@ class Migrate extends Action $totalProjects = $dbForConsole->count('projects') + 1; } - $class = 'Appwrite\\Migration\\Version\\'.Migration::$versions[$version]; + $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; $migration = new $class(); - while (! empty($projects)) { + while (!empty($projects)) { foreach ($projects as $project) { /** * Skip user projects with id 'console' @@ -100,7 +99,7 @@ class Migrate extends Action ->setProject($project, $projectDB, $dbForConsole) ->execute(); } catch (\Throwable $th) { - Console::error('Failed to update project ("'.$project->getId().'") version with error: '.$th->getMessage()); + Console::error('Failed to update project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); throw $th; } @@ -113,7 +112,7 @@ class Migrate extends Action $offset = $offset + $limit; $count = $count + $sum; - Console::log('Migrated '.$count.'/'.$totalProjects.' projects...'); + Console::log('Migrated ' . $count . '/' . $totalProjects . ' projects...'); } Swoole\Event::wait(); // Wait for Coroutines to finish diff --git a/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php b/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php index 9724818f70..74ef644498 100644 --- a/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php +++ b/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php @@ -2,14 +2,14 @@ namespace Appwrite\Platform\Tasks; +use Utopia\Platform\Action; use Utopia\CLI\Console; -use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Helpers\ID; use Utopia\Database\Query; +use Utopia\Database\Database; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; -use Utopia\Platform\Action; class PatchCreateMissingSchedules extends Action { @@ -36,7 +36,7 @@ class PatchCreateMissingSchedules extends Action Authorization::setDefaultStatus(false); Console::title('PatchCreateMissingSchedules V1'); - Console::success(APP_NAME.' PatchCreateMissingSchedules v1 has started'); + Console::success(APP_NAME . ' PatchCreateMissingSchedules v1 has started'); $limit = 100; $projectCursor = null; @@ -52,7 +52,7 @@ class PatchCreateMissingSchedules extends Action } foreach ($projects as $project) { - Console::log('Checking Project '.$project->getAttribute('name').' ('.$project->getId().')'); + Console::log("Checking Project " . $project->getAttribute('name') . " (" . $project->getId() . ")"); $dbForProject = $getProjectDB($project); $functionCursor = null; @@ -79,11 +79,11 @@ class PatchCreateMissingSchedules extends Action 'resourceId' => $functionId, 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), - 'schedule' => $function->getAttribute('schedule'), - 'active' => ! empty($function->getAttribute('schedule')) && ! empty($function->getAttribute('deployment')), + 'schedule' => $function->getAttribute('schedule'), + 'active' => !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment')), ])); - Console::success('Recreated schedule for function '.$functionId); + Console::success('Recreated schedule for function ' . $functionId); } } diff --git a/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php b/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php index 3a70e239cb..a909e68595 100644 --- a/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php +++ b/src/Appwrite/Platform/Tasks/PatchDeleteProjectCollections.php @@ -3,11 +3,11 @@ namespace Appwrite\Platform\Tasks; use Utopia\App; +use Utopia\Platform\Action; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Query; -use Utopia\Platform\Action; use Utopia\Pools\Group; use Utopia\Validator\Numeric; @@ -31,6 +31,7 @@ class PatchDeleteProjectCollections extends Action public function __construct() { + $this ->desc('Delete unnecessary project collections') ->param('offset', 0, new Numeric(), 'Resume deletion from param pos', true) @@ -47,7 +48,7 @@ class PatchDeleteProjectCollections extends Action //docker compose exec -t appwrite patch-delete-project-collections Console::title('Delete project collections V1'); - Console::success(APP_NAME.' delete project collections has started'); + Console::success(APP_NAME . ' delete project collections has started'); /* Initialise new Utopia app */ $app = new App('UTC'); @@ -62,8 +63,9 @@ class PatchDeleteProjectCollections extends Action $limit = 50; $sum = 50; $offset = $offset; - while (! empty($projects)) { + while (!empty($projects)) { foreach ($projects as $project) { + /** * Skip user projects with id 'console' */ @@ -82,7 +84,7 @@ class PatchDeleteProjectCollections extends Action $dbForProject = new Database($adapter, $cache); $dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $dbForProject->setNamespace('_'.$project->getInternalId()); + $dbForProject->setNamespace('_' . $project->getInternalId()); foreach ($this->names as $name) { if (empty($name)) { @@ -90,14 +92,14 @@ class PatchDeleteProjectCollections extends Action } if ($dbForProject->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { if ($dbForProject->deleteCollection($name)) { - Console::log('Deleted '.$name); + Console::log('Deleted ' . $name); } else { - Console::error('Failed to delete '.$name); + Console::error('Failed to delete ' . $name); } } } } catch (\Throwable $th) { - Console::error('Failed on project ("'.$project->getId().'") version with error: '.$th->getMessage()); + Console::error('Failed on project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); } finally { $pools ->get($db) @@ -112,14 +114,14 @@ class PatchDeleteProjectCollections extends Action Query::offset($offset), ]); - if (! empty($projects)) { - Console::log('Querying..... offset='.$offset.' , limit='.$limit.', count='.$count); + if (!empty($projects)) { + Console::log('Querying..... offset=' . $offset . ' , limit=' . $limit . ', count=' . $count); } $offset = $offset + $limit; $count = $count + $sum; } - Console::log('Iterated through '.$count - 1 .'/'.$totalProjects.' projects...'); + Console::log('Iterated through ' . $count - 1 . '/' . $totalProjects . ' projects...'); $pools ->get('console') ->reclaim(); diff --git a/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php b/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php index b8fd8baaa2..95a7c4ffe1 100644 --- a/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php +++ b/src/Appwrite/Platform/Tasks/PatchDeleteScheduleUpdatedAtAttribute.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Tasks; -use Utopia\CLI\Console; -use Utopia\Database\Database; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; +use Utopia\CLI\Console; +use Utopia\Database\Query; +use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class PatchDeleteScheduleUpdatedAtAttribute extends Action @@ -35,7 +35,7 @@ class PatchDeleteScheduleUpdatedAtAttribute extends Action Authorization::setDefaultStatus(false); Console::title('PatchDeleteScheduleUpdatedAtAttribute V1'); - Console::success(APP_NAME.' PatchDeleteScheduleUpdatedAtAttribute v1 has started'); + Console::success(APP_NAME . ' PatchDeleteScheduleUpdatedAtAttribute v1 has started'); $limit = 100; $projectCursor = null; @@ -51,7 +51,7 @@ class PatchDeleteScheduleUpdatedAtAttribute extends Action } foreach ($projects as $project) { - Console::log('Checking Project '.$project->getAttribute('name').' ('.$project->getId().')'); + Console::log("Checking Project " . $project->getAttribute('name') . " (" . $project->getId() . ")"); $dbForProject = $getProjectDB($project); try { diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index 4b2c07e17c..f70ae8bd60 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -2,8 +2,8 @@ namespace Appwrite\Platform\Tasks; +use Utopia\Platform\Action; use Appwrite\SDK\Language\Android; -use Appwrite\SDK\Language\Apple; use Appwrite\SDK\Language\CLI; use Appwrite\SDK\Language\Dart; use Appwrite\SDK\Language\Deno; @@ -18,14 +18,14 @@ use Appwrite\SDK\Language\Python; use Appwrite\SDK\Language\REST; use Appwrite\SDK\Language\Ruby; use Appwrite\SDK\Language\Swift; +use Exception; +use Throwable; +use Appwrite\SDK\Language\Apple; use Appwrite\SDK\Language\Web; use Appwrite\SDK\SDK; use Appwrite\Spec\Swagger2; -use Exception; -use Throwable; use Utopia\CLI\Console; use Utopia\Config\Config; -use Utopia\Platform\Action; class SDKs extends Action { @@ -44,14 +44,14 @@ class SDKs extends Action public function action(): void { $platforms = Config::getParam('platforms'); - $selectedPlatform = Console::confirm('Choose Platform ("'.APP_PLATFORM_CLIENT.'", "'.APP_PLATFORM_SERVER.'", "'.APP_PLATFORM_CONSOLE.'" or "*" for all):'); + $selectedPlatform = Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); $selectedSDK = \strtolower(Console::confirm('Choose SDK ("*" for all):')); $version = Console::confirm('Choose an Appwrite version'); $git = (Console::confirm('Should we use git push? (yes/no)') == 'yes'); $production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false; $message = ($git) ? Console::confirm('Please enter your commit message:') : ''; - if (! in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', 'latest'])) { + if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', 'latest'])) { throw new Exception('Unknown version given'); } @@ -65,31 +65,30 @@ class SDKs extends Action continue; } - if (! $language['enabled']) { - Console::warning($language['name'].' for '.$platform['name'].' is disabled'); - + if (!$language['enabled']) { + Console::warning($language['name'] . ' for ' . $platform['name'] . ' is disabled'); continue; } - Console::info('Fetching API Spec for '.$language['name'].' for '.$platform['name'].' (version: '.$version.')'); + Console::info('Fetching API Spec for ' . $language['name'] . ' for ' . $platform['name'] . ' (version: ' . $version . ')'); - $spec = file_get_contents(__DIR__.'/../../../../app/config/specs/swagger2-'.$version.'-'.$language['family'].'.json'); + $spec = file_get_contents(__DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $language['family'] . '.json'); $cover = 'https://appwrite.io/images/github.png'; - $result = \realpath(__DIR__.'/../../../../app').'/sdks/'.$key.'-'.$language['key']; - $resultExamples = \realpath(__DIR__.'/../../../..').'/docs/examples/'.$version.'/'.$key.'-'.$language['key']; - $target = \realpath(__DIR__.'/../../../../app').'/sdks/git/'.$language['key'].'/'; - $readme = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/README.md'); + $result = \realpath(__DIR__ . '/../../../../app') . '/sdks/' . $key . '-' . $language['key']; + $resultExamples = \realpath(__DIR__ . '/../../../..') . '/docs/examples/' . $version . '/' . $key . '-' . $language['key']; + $target = \realpath(__DIR__ . '/../../../../app') . '/sdks/git/' . $language['key'] . '/'; + $readme = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/README.md'); $readme = ($readme) ? \file_get_contents($readme) : ''; - $gettingStarted = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/GETTING_STARTED.md'); + $gettingStarted = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/GETTING_STARTED.md'); $gettingStarted = ($gettingStarted) ? \file_get_contents($gettingStarted) : ''; - $examples = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/EXAMPLES.md'); + $examples = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/EXAMPLES.md'); $examples = ($examples) ? \file_get_contents($examples) : ''; - $changelog = \realpath(__DIR__.'/../../../../docs/sdks/'.$language['key'].'/CHANGELOG.md'); + $changelog = \realpath(__DIR__ . '/../../../../docs/sdks/' . $language['key'] . '/CHANGELOG.md'); $changelog = ($changelog) ? \file_get_contents($changelog) : '# Change Log'; - $warning = '**This SDK is compatible with Appwrite server version '.$version.'. For older versions, please check [previous releases]('.$language['url'].'/releases).**'; + $warning = '**This SDK is compatible with Appwrite server version ' . $version . '. For older versions, please check [previous releases](' . $language['url'] . '/releases).**'; $license = 'BSD-3-Clause'; - $licenseContent = 'Copyright (c) '.date('Y').' Appwrite (https://appwrite.io) and individual contributors. + $licenseContent = 'Copyright (c) ' . date('Y') . ' Appwrite (https://appwrite.io) and individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -143,7 +142,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $config = new Node(); $config->setNPMPackage('node-appwrite'); $config->setBowerPackage('appwrite'); - $warning = $warning."\n\n > This is the Node.js SDK for integrating with Appwrite from your Node.js server-side code. + $warning = $warning . "\n\n > This is the Node.js SDK for integrating with Appwrite from your Node.js server-side code. If you're looking to integrate from the browser, you should check [appwrite/sdk-for-web](https://github.com/appwrite/sdk-for-web)"; break; case 'deno': @@ -169,14 +168,14 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND case 'dart': $config = new Dart(); $config->setPackageName('dart_appwrite'); - $warning = $warning."\n\n > This is the Dart SDK for integrating with Appwrite from your Dart server-side code. If you're looking for the Flutter SDK you should check [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter)"; + $warning = $warning . "\n\n > This is the Dart SDK for integrating with Appwrite from your Dart server-side code. If you're looking for the Flutter SDK you should check [appwrite/sdk-for-flutter](https://github.com/appwrite/sdk-for-flutter)"; break; case 'go': $config = new Go(); break; case 'swift': $config = new Swift(); - $warning = $warning."\n\n > This is the Swift SDK for integrating with Appwrite from your Swift server-side code. If you're looking for the Apple SDK you should check [appwrite/sdk-for-apple](https://github.com/appwrite/sdk-for-apple)"; + $warning = $warning . "\n\n > This is the Swift SDK for integrating with Appwrite from your Swift server-side code. If you're looking for the Apple SDK you should check [appwrite/sdk-for-apple](https://github.com/appwrite/sdk-for-apple)"; break; case 'apple': $config = new Apple(); @@ -190,7 +189,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND break; case 'kotlin': $config = new Kotlin(); - $warning = $warning."\n\n > This is the Kotlin SDK for integrating with Appwrite from your Kotlin server-side code. If you're looking for the Android SDK you should check [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android)"; + $warning = $warning . "\n\n > This is the Kotlin SDK for integrating with Appwrite from your Kotlin server-side code. If you're looking for the Android SDK you should check [appwrite/sdk-for-android](https://github.com/appwrite/sdk-for-android)"; break; case 'graphql': $config = new GraphQL(); @@ -199,7 +198,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $config = new REST(); break; default: - throw new Exception('Language "'.$language['key'].'" not supported'); + throw new Exception('Language "' . $language['key'] . '" not supported'); } Console::info("Generating {$language['name']} SDK..."); @@ -247,28 +246,29 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $gitUrl = $language['gitUrl']; $gitBranch = $language['gitBranch']; - if (! $production) { - $gitUrl = 'git@github.com:aw-tests/'.$language['gitRepoName'].'.git'; + + if (!$production) { + $gitUrl = 'git@github.com:aw-tests/' . $language['gitRepoName'] . '.git'; } - if ($git && ! empty($gitUrl)) { - \exec('rm -rf '.$target.' && \ - mkdir -p '.$target.' && \ - cd '.$target.' && \ - git init --initial-branch='.$gitBranch.' && \ - git remote add origin '.$gitUrl.' && \ - git fetch origin '.$gitBranch.' && \ - git pull origin '.$gitBranch.' && \ - rm -rf '.$target.'/* && \ - cp -r '.$result.'/* '.$target.'/ && \ + if ($git && !empty($gitUrl)) { + \exec('rm -rf ' . $target . ' && \ + mkdir -p ' . $target . ' && \ + cd ' . $target . ' && \ + git init --initial-branch=' . $gitBranch . ' && \ + git remote add origin ' . $gitUrl . ' && \ + git fetch origin ' . $gitBranch . ' && \ + git pull origin ' . $gitBranch . ' && \ + rm -rf ' . $target . '/* && \ + cp -r ' . $result . '/* ' . $target . '/ && \ git add . && \ - git commit -m "'.$message.'" && \ - git push -u origin '.$gitBranch.' + git commit -m "' . $message . '" && \ + git push -u origin ' . $gitBranch . ' '); Console::success("Pushed {$language['name']} SDK to {$gitUrl}"); - \exec('rm -rf '.$target); + \exec('rm -rf ' . $target); Console::success("Remove temp directory '{$target}' for {$language['name']} SDK"); } @@ -279,10 +279,10 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND } foreach ($docDirectories as $languageTitle => $path) { - $languagePath = strtolower($languageTitle !== 0 ? '/'.$languageTitle : ''); + $languagePath = strtolower($languageTitle !== 0 ? '/' . $languageTitle : ''); \exec( - 'mkdir -p '.$resultExamples.$languagePath.' && \ - cp -r '.$result.'/docs/examples'.$languagePath.' '.$resultExamples + 'mkdir -p ' . $resultExamples . $languagePath . ' && \ + cp -r ' . $result . '/docs/examples' . $languagePath . ' ' . $resultExamples ); Console::success("Copied code examples for {$language['name']} SDK to: {$resultExamples}"); } diff --git a/src/Appwrite/Platform/Tasks/SSL.php b/src/Appwrite/Platform/Tasks/SSL.php index 9697ff91ae..43026b0753 100644 --- a/src/Appwrite/Platform/Tasks/SSL.php +++ b/src/Appwrite/Platform/Tasks/SSL.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Tasks; +use Utopia\Platform\Action; use Appwrite\Event\Certificate; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Document; -use Utopia\Platform\Action; use Utopia\Validator\Hostname; class SSL extends Action @@ -26,11 +26,11 @@ class SSL extends Action public function action(string $domain): void { - Console::success('Scheduling a job to issue a TLS certificate for domain: '.$domain); + Console::success('Scheduling a job to issue a TLS certificate for domain: ' . $domain); (new Certificate()) ->setDomain(new Document([ - 'domain' => $domain, + 'domain' => $domain ])) ->setSkipRenewCheck(true) ->trigger(); diff --git a/src/Appwrite/Platform/Tasks/Schedule.php b/src/Appwrite/Platform/Tasks/Schedule.php index 42e8327e9a..219d1c9886 100644 --- a/src/Appwrite/Platform/Tasks/Schedule.php +++ b/src/Appwrite/Platform/Tasks/Schedule.php @@ -2,23 +2,23 @@ namespace Appwrite\Platform\Tasks; -use Appwrite\Event\Func; use Cron\CronExpression; -use function Swoole\Coroutine\run; use Swoole\Timer; use Utopia\App; +use Utopia\Platform\Action; use Utopia\CLI\Console; -use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Platform\Action; +use Utopia\Database\Database; use Utopia\Pools\Group; +use Appwrite\Event\Func; + +use function Swoole\Coroutine\run; class Schedule extends Action { public const FUNCTION_UPDATE_TIMER = 10; //seconds - public const FUNCTION_ENQUEUE_TIMER = 60; //seconds public static function getName(): string @@ -40,17 +40,16 @@ class Schedule extends Action * 1. Load all documents from 'schedules' collection to create local copy * 2. Create timer that sync all changes from 'schedules' collection to local copy. Only reading changes thanks to 'resourceUpdatedAt' attribute * 3. Create timer that prepares coroutines for soon-to-execute schedules. When it's ready, coroutime sleeps until exact time before sending request to worker. - */ + */ public function action(Group $pools, Database $dbForConsole, callable $getProjectDB): void { Console::title('Scheduler V1'); - Console::success(APP_NAME.' Scheduler v1 has started'); + Console::success(APP_NAME . ' Scheduler v1 has started'); /** * Extract only nessessary attributes to lower memory used. * * @var Document $schedule - * * @return array */ $getSchedule = function (Document $schedule) use ($dbForConsole, $getProjectDB): array { @@ -93,14 +92,14 @@ class Schedule extends Action $schedules[$document['resourceId']] = $getSchedule($document); } - $latestDocument = ! empty(array_key_last($results)) ? $results[array_key_last($results)] : null; + $latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null; } $pools->reclaim(); - Console::success("{$total} functions were loaded in ".(microtime(true) - $loadStart).' seconds'); + Console::success("{$total} functions were loaded in " . (microtime(true) - $loadStart) . " seconds"); - Console::success('Starting timers at '.DateTime::now()); + Console::success("Starting timers at " . DateTime::now()); run( function () use ($dbForConsole, &$schedules, &$lastSyncUpdate, $getSchedule, $pools) { @@ -121,7 +120,7 @@ class Schedule extends Action while ($sum === $limit) { $paginationQueries = [Query::limit($limit)]; if ($latestDocument !== null) { - $paginationQueries[] = Query::cursorAfter($latestDocument); + $paginationQueries[] = Query::cursorAfter($latestDocument); } $results = $dbForConsole->find('schedules', \array_merge($paginationQueries, [ Query::equal('region', [App::getEnv('_APP_REGION', 'default')]), @@ -145,7 +144,7 @@ class Schedule extends Action $schedules[$document['resourceId']] = $getSchedule($document); } } - $latestDocument = ! empty(array_key_last($results)) ? $results[array_key_last($results)] : null; + $latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null; } $lastSyncUpdate = $time; @@ -153,7 +152,7 @@ class Schedule extends Action $pools->reclaim(); - Console::log("Sync tick: {$total} schedules were updated in ".($timerEnd - $timerStart).' seconds'); + Console::log("Sync tick: {$total} schedules were updated in " . ($timerEnd - $timerStart) . " seconds"); }); /** @@ -180,7 +179,7 @@ class Schedule extends Action $currentTick = $next < $timeFrame; - if (! $currentTick) { + if (!$currentTick) { continue; } @@ -190,7 +189,7 @@ class Schedule extends Action $executionStart = $nextDate->getTimestamp(); // in seconds $delay = $executionStart - $promiseStart; // Time to wait from now until execution needs to be queued - if (! isset($delayedExecutions[$delay])) { + if (!isset($delayedExecutions[$delay])) { $delayedExecutions[$delay] = []; } @@ -206,7 +205,7 @@ class Schedule extends Action foreach ($scheduleKeys as $scheduleKey) { // Ensure schedule was not deleted - if (! isset($schedules[$scheduleKey])) { + if (!isset($schedules[$scheduleKey])) { return; } @@ -227,10 +226,10 @@ class Schedule extends Action $timerEnd = \microtime(true); $lastEnqueueUpdate = $timerStart; - Console::log("Enqueue tick: {$total} executions were enqueued in ".($timerEnd - $timerStart).' seconds'); + Console::log("Enqueue tick: {$total} executions were enqueued in " . ($timerEnd - $timerStart) . " seconds"); }; - Timer::tick(self::FUNCTION_ENQUEUE_TIMER * 1000, fn () => $enqueueFunctions()); + Timer::tick(self::FUNCTION_ENQUEUE_TIMER * 1000, fn() => $enqueueFunctions()); $enqueueFunctions(); } ); diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index d596a36925..82caf8ef72 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -2,6 +2,8 @@ namespace Appwrite\Platform\Tasks; +use Utopia\Platform\Action; +use Utopia\Validator\Text; use Appwrite\Specification\Format\OpenAPI3; use Appwrite\Specification\Format\Swagger2; use Appwrite\Specification\Specification; @@ -15,10 +17,8 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Adapter\MySQL; use Utopia\Database\Database; -use Utopia\Platform\Action; use Utopia\Registry\Registry; use Utopia\Request; -use Utopia\Validator\Text; use Utopia\Validator\WhiteList; class Specs extends Action @@ -177,15 +177,15 @@ class Specs extends Action $sdkPlaforms[] = APP_PLATFORM_CLIENT; } - if (! $route->getLabel('docs', true)) { + if (!$route->getLabel('docs', true)) { continue; } - if ($route->getLabel('sdk.mock', false) && ! $mocks) { + if ($route->getLabel('sdk.mock', false) && !$mocks) { continue; } - if (! $route->getLabel('sdk.mock', false) && $mocks) { + if (!$route->getLabel('sdk.mock', false) && $mocks) { continue; } @@ -193,7 +193,7 @@ class Specs extends Action continue; } - if ($platform !== APP_PLATFORM_CONSOLE && ! \in_array($platforms[$platform], $sdkPlaforms)) { + if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlaforms)) { continue; } @@ -203,10 +203,10 @@ class Specs extends Action foreach (Config::getParam('services', []) as $service) { if ( - ! isset($service['docs']) // Skip service if not part of the public API - || ! isset($service['sdk']) - || ! $service['docs'] - || ! $service['sdk'] + !isset($service['docs']) // Skip service if not part of the public API + || !isset($service['sdk']) + || !$service['docs'] + || !$service['sdk'] ) { continue; } @@ -221,7 +221,7 @@ class Specs extends Action $models = $response->getModels(); foreach ($models as $key => $value) { - if ($platform !== APP_PLATFORM_CONSOLE && ! $value->isPublic()) { + if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) { unset($models[$key]); } } @@ -231,7 +231,7 @@ class Specs extends Action $formatInstance = match ($format) { 'swagger2' => new Swagger2(...$arguments), 'open-api3' => new OpenAPI3(...$arguments), - default => throw new Exception('Format not found: '.$format) + default => throw new Exception('Format not found: ' . $format) }; $specs = new Specification($formatInstance); @@ -243,36 +243,36 @@ class Specs extends Action ->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)') ->setParam('endpoint', 'https://HOSTNAME/v1') ->setParam('version', APP_VERSION_STABLE) - ->setParam('terms', $endpoint.'/policy/terms') + ->setParam('terms', $endpoint . '/policy/terms') ->setParam('support.email', $email) - ->setParam('support.url', $endpoint.'/support') - ->setParam('contact.name', APP_NAME.' Team') + ->setParam('support.url', $endpoint . '/support') + ->setParam('contact.name', APP_NAME . ' Team') ->setParam('contact.email', $email) - ->setParam('contact.url', $endpoint.'/support') + ->setParam('contact.url', $endpoint . '/support') ->setParam('license.name', 'BSD-3-Clause') ->setParam('license.url', 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE') ->setParam('docs.description', 'Full API docs, specs and tutorials') - ->setParam('docs.url', $endpoint.'/docs'); + ->setParam('docs.url', $endpoint . '/docs'); if ($mocks) { - $path = __DIR__.'/../config/specs/'.$format.'-mocks-'.$platform.'.json'; + $path = __DIR__ . '/../config/specs/' . $format . '-mocks-' . $platform . '.json'; - if (! file_put_contents($path, json_encode($specs->parse()))) { - throw new Exception('Failed to save mocks spec file: '.$path); + if (!file_put_contents($path, json_encode($specs->parse()))) { + throw new Exception('Failed to save mocks spec file: ' . $path); } - Console::success('Saved mocks spec file: '.realpath($path)); + Console::success('Saved mocks spec file: ' . realpath($path)); continue; } - $path = __DIR__.'/../../../../app/config/specs/'.$format.'-'.$version.'-'.$platform.'.json'; + $path = __DIR__ . '/../../../../app/config/specs/' . $format . '-' . $version . '-' . $platform . '.json'; - if (! file_put_contents($path, json_encode($specs->parse()))) { - throw new Exception('Failed to save spec file: '.$path); + if (!file_put_contents($path, json_encode($specs->parse()))) { + throw new Exception('Failed to save spec file: ' . $path); } - Console::success('Saved spec file: '.realpath($path)); + Console::success('Saved spec file: ' . realpath($path)); } } } diff --git a/src/Appwrite/Platform/Tasks/Vars.php b/src/Appwrite/Platform/Tasks/Vars.php index 714bb40ab1..c97f77a9da 100644 --- a/src/Appwrite/Platform/Tasks/Vars.php +++ b/src/Appwrite/Platform/Tasks/Vars.php @@ -3,8 +3,8 @@ namespace Appwrite\Platform\Tasks; use Utopia\App; -use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\CLI\Console; use Utopia\Platform\Action; class Vars extends Action @@ -33,7 +33,7 @@ class Vars extends Action } foreach ($vars as $key => $value) { - Console::log('- '.$value['name'].'='.App::getEnv($value['name'], '')); + Console::log('- ' . $value['name'] . '=' . App::getEnv($value['name'], '')); } } } diff --git a/src/Appwrite/Platform/Tasks/VolumeSync.php b/src/Appwrite/Platform/Tasks/VolumeSync.php index 193d07fd17..6197b20fbd 100644 --- a/src/Appwrite/Platform/Tasks/VolumeSync.php +++ b/src/Appwrite/Platform/Tasks/VolumeSync.php @@ -27,10 +27,11 @@ class VolumeSync extends Action public function action(string $source, string $destination, int $interval) { - Console::title('RSync V1'); - Console::success(APP_NAME.' rsync process v1 has started'); - if (! file_exists($source)) { + Console::title('RSync V1'); + Console::success(APP_NAME . ' rsync process v1 has started'); + + if (!file_exists($source)) { Console::error('Source directory does not exist. Exiting ... '); Console::exit(0); } @@ -41,15 +42,14 @@ class VolumeSync extends Action Console::info("[{$time}] Executing rsync every {$interval} seconds"); Console::info("Syncing between $source and $destination"); - if (! file_exists($source)) { + if (!file_exists($source)) { Console::error('Source directory does not exist. Skipping ... '); - return; } - $stdin = ''; - $stdout = ''; - $stderr = ''; + $stdin = ""; + $stdout = ""; + $stderr = ""; Console::execute("rsync -av $source $destination", $stdin, $stdout, $stderr); Console::success($stdout); diff --git a/src/Appwrite/Promises/Promise.php b/src/Appwrite/Promises/Promise.php index 95e4c7bc69..a6b1aa79d5 100644 --- a/src/Appwrite/Promises/Promise.php +++ b/src/Appwrite/Promises/Promise.php @@ -5,9 +5,7 @@ namespace Appwrite\Promises; abstract class Promise { protected const STATE_PENDING = 1; - protected const STATE_FULFILLED = 0; - protected const STATE_REJECTED = -1; protected int $state = self::STATE_PENDING; @@ -39,7 +37,7 @@ abstract class Promise /** * Create a new promise from the given callable. * - * @param callable $promise + * @param callable $promise * @return self */ public static function create(callable $promise): self @@ -50,7 +48,7 @@ abstract class Promise /** * Resolve promise with given value. * - * @param mixed $value + * @param mixed $value * @return self */ public static function resolve(mixed $value): self @@ -63,7 +61,7 @@ abstract class Promise /** * Rejects the promise with the given reason. * - * @param mixed $value + * @param mixed $value * @return self */ public static function reject(mixed $value): self @@ -76,7 +74,7 @@ abstract class Promise /** * Catch any exception thrown by the executor. * - * @param callable $onRejected + * @param callable $onRejected * @return self */ public function catch(callable $onRejected): self @@ -87,8 +85,8 @@ abstract class Promise /** * Execute the promise. * - * @param callable|null $onFulfilled - * @param callable|null $onRejected + * @param callable|null $onFulfilled + * @param callable|null $onRejected * @return self */ public function then( @@ -101,15 +99,13 @@ abstract class Promise if ($this->isFulfilled() && $onFulfilled === null) { return $this; } - return self::create(function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected) { while ($this->isPending()) { usleep(25000); } $callable = $this->isFulfilled() ? $onFulfilled : $onRejected; - if (! \is_callable($callable)) { + if (!\is_callable($callable)) { $resolve($this->result); - return; } try { @@ -123,7 +119,7 @@ abstract class Promise /** * Returns a promise that completes when all passed in promises complete. * - * @param iterable|self[] $promises + * @param iterable|self[] $promises * @return self */ abstract public static function all(iterable $promises): self; @@ -131,14 +127,13 @@ abstract class Promise /** * Set resolved result * - * @param mixed $value + * @param mixed $value * @return void */ protected function setResult(mixed $value): void { - if (! \is_callable([$value, 'then'])) { + if (!\is_callable([$value, 'then'])) { $this->result = $value; - return; } @@ -151,7 +146,7 @@ abstract class Promise $value->then($callable, $callable); - while (! $resolved) { + while (!$resolved) { usleep(25000); } } @@ -159,7 +154,7 @@ abstract class Promise /** * Change promise state * - * @param int $state + * @param integer $state * @return void */ protected function setState(int $state): void @@ -170,7 +165,7 @@ abstract class Promise /** * Promise is pending * - * @return bool + * @return boolean */ protected function isPending(): bool { @@ -180,7 +175,7 @@ abstract class Promise /** * Promise is fulfilled * - * @return bool + * @return boolean */ protected function isFulfilled(): bool { @@ -190,7 +185,7 @@ abstract class Promise /** * Promise is rejected * - * @return bool + * @return boolean */ protected function isRejected(): bool { diff --git a/src/Appwrite/Promises/Swoole.php b/src/Appwrite/Promises/Swoole.php index 4867ed6c96..c258ef6a5e 100644 --- a/src/Appwrite/Promises/Swoole.php +++ b/src/Appwrite/Promises/Swoole.php @@ -28,7 +28,7 @@ class Swoole extends Promise /** * Returns a promise that completes when all passed in promises complete. * - * @param iterable|Swoole[] $promises + * @param iterable|Swoole[] $promises * @return Promise */ public static function all(iterable $promises): Promise @@ -45,7 +45,6 @@ class Swoole extends Promise $promise->then(function ($value) use ($key, &$result, $channel) { $result[$key] = $value; $channel->push(true); - return $value; }, function ($err) use ($channel, &$error) { $channel->push(true); @@ -62,7 +61,6 @@ class Swoole extends Promise if ($error !== null) { $reject($error); - return; } diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index f6ff7c2fb8..146500e743 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -5,14 +5,12 @@ namespace Appwrite\Resque; use Appwrite\Event\Usage; use Exception; use Utopia\App; -use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; -use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Cache\Adapter\Sharding; +use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; -use Utopia\DSN\DSN; use Utopia\Pools\Group; use Utopia\Storage\Device; use Utopia\Storage\Device\Backblaze; @@ -20,6 +18,8 @@ use Utopia\Storage\Device\DOSpaces; use Utopia\Storage\Device\Linode; use Utopia\Storage\Device\Local; use Utopia\Storage\Device\S3; +use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Storage\Device\Wasabi; use Utopia\Storage\Storage; @@ -43,12 +43,11 @@ abstract class Worker * Function for identifying the worker needs to be set to unique name * * @return string - * * @throws Exception */ public function getName(): string { - throw new Exception('Please implement getName method in worker'); + throw new Exception("Please implement getName method in worker"); } /** @@ -56,12 +55,11 @@ abstract class Worker * Can include any preparations, such as connecting to external services or loading files * * @return void - * * @throws \Exception|\Throwable */ public function init(): void { - throw new Exception('Please implement init method in worker'); + throw new Exception("Please implement init method in worker"); } /** @@ -69,12 +67,11 @@ abstract class Worker * You can access $args here, it will contain event information * * @return void - * * @throws \Exception|\Throwable */ public function run(): void { - throw new Exception('Please implement run method in worker'); + throw new Exception("Please implement run method in worker"); } /** @@ -82,23 +79,20 @@ abstract class Worker * You can do cleanup here, such as disconnecting from services or removing temp files * * @return void - * * @throws \Exception|\Throwable */ public function shutdown(): void { - throw new Exception('Please implement shutdown method in worker'); + throw new Exception("Please implement shutdown method in worker"); } public const DATABASE_PROJECT = 'project'; - public const DATABASE_CONSOLE = 'console'; /** * A wrapper around 'init' function with non-worker-specific code * * @return void - * * @throws \Exception|\Throwable */ public function setUp(): void @@ -107,7 +101,7 @@ abstract class Worker $this->init(); } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { - $errorCallback($error, 'init', $this->getName()); + $errorCallback($error, "init", $this->getName()); } throw $error; @@ -118,7 +112,6 @@ abstract class Worker * A wrapper around 'run' function with non-worker-specific code * * @return void - * * @throws \Exception|\Throwable */ public function perform(): void @@ -132,7 +125,7 @@ abstract class Worker $this->run(); } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { - $errorCallback($error, 'run', $this->getName(), $this->args); + $errorCallback($error, "run", $this->getName(), $this->args); } throw $error; @@ -143,7 +136,6 @@ abstract class Worker * A wrapper around 'shutdown' function with non-worker-specific code * * @return void - * * @throws \Exception|\Throwable */ public function tearDown(): void @@ -157,17 +149,17 @@ abstract class Worker $this->shutdown(); } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { - $errorCallback($error, 'shutdown', $this->getName()); + $errorCallback($error, "shutdown", $this->getName()); } throw $error; } } + /** * Register callback. Will be executed when error occurs. - * - * @param callable $callback + * @param callable $callback * @return void */ public static function error(callable $callback): void @@ -177,10 +169,8 @@ abstract class Worker /** * Get internal project database - * - * @param Document $project + * @param Document $project * @return Database - * * @throws Exception */ protected static $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools @@ -190,6 +180,7 @@ abstract class Worker global $register; $pools = $register->get('pools'); /** @var Group $pools */ + if ($project->isEmpty() || $project->getId() === 'console') { return $this->getConsoleDB(); } @@ -198,30 +189,28 @@ abstract class Worker if (isset(self::$databases[$databaseName])) { $database = self::$databases[$databaseName]; - $database->setNamespace('_'.$project->getInternalId()); - + $database->setNamespace('_' . $project->getInternalId()); return $database; } $dbAdapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource(); + ->getResource() + ; $database = new Database($dbAdapter, $this->getCache()); self::$databases[$databaseName] = $database; - $database->setNamespace('_'.$project->getInternalId()); + $database->setNamespace('_' . $project->getInternalId()); return $database; } /** * Get console database - * * @return Database - * * @throws Exception */ protected function getConsoleDB(): Database @@ -229,19 +218,20 @@ abstract class Worker global $register; $pools = $register->get('pools'); /** @var Group $pools */ + $databaseName = 'console'; if (isset(self::$databases[$databaseName])) { $database = self::$databases[$databaseName]; $database->setNamespace('console'); - return $database; } $dbAdapter = $pools ->get('console') ->pop() - ->getResource(); + ->getResource() + ; $database = new Database($dbAdapter, $this->getCache()); @@ -252,9 +242,9 @@ abstract class Worker return $database; } + /** * Get Cache - * * @return Cache */ protected function getCache(): Cache @@ -262,6 +252,7 @@ abstract class Worker global $register; $pools = $register->get('pools'); /** @var Group $pools */ + $list = Config::getParam('pools-cache', []); $adapters = []; @@ -269,7 +260,8 @@ abstract class Worker $adapters[] = $pools ->get($value) ->pop() - ->getResource(); + ->getResource() + ; } return new Cache(new Sharding($adapters)); @@ -277,9 +269,7 @@ abstract class Worker /** * Get usage queue - * * @return Usage - * * @throws Exception */ protected function getUsageQueue(): Usage @@ -297,46 +287,42 @@ abstract class Worker /** * Get Functions Storage Device - * - * @param string $projectId of the project + * @param string $projectId of the project * @return Device */ protected function getFunctionsDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_FUNCTIONS.'/app-'.$projectId); + return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId); } /** * Get Files Storage Device - * - * @param string $projectId of the project + * @param string $projectId of the project * @return Device */ protected function getFilesDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_UPLOADS.'/app-'.$projectId); + return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId); } /** * Get Builds Storage Device - * - * @param string $projectId of the project + * @param string $projectId of the project * @return Device */ protected function getBuildsDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_BUILDS.'/app-'.$projectId); + return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId); } protected function getCacheDevice(string $projectId): Device { - return $this->getDevice(APP_STORAGE_CACHE.'/app-'.$projectId); + return $this->getDevice(APP_STORAGE_CACHE . '/app-' . $projectId); } /** * Get Device based on selected storage environment - * - * @param string $root path of the device + * @param string $root path of the device * @return Device */ public function getDevice(string $root): Device @@ -357,7 +343,7 @@ abstract class Worker $bucket = $dsn->getPath(); $region = $dsn->getParam('region'); } catch (\Exception $e) { - Console::error($e->getMessage().'Invalid DSN. Defaulting to Local device.'); + Console::error($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); } switch ($device) { diff --git a/src/Appwrite/Specification/Format.php b/src/Appwrite/Specification/Format.php index 670fbceecb..c2317c1153 100644 --- a/src/Appwrite/Specification/Format.php +++ b/src/Appwrite/Specification/Format.php @@ -2,10 +2,10 @@ namespace Appwrite\Specification; -use Appwrite\Utopia\Response\Model; use Utopia\App; use Utopia\Config\Config; use Utopia\Route; +use Appwrite\Utopia\Response\Model; abstract class Format { @@ -22,11 +22,8 @@ abstract class Format protected array $models; protected array $services; - protected array $keys; - protected int $authCount; - protected array $params = [ 'name' => '', 'description' => '', @@ -49,8 +46,8 @@ abstract class Format [ 'namespace' => 'users', 'method' => 'getUsage', - 'parameter' => 'provider', - ], + 'parameter' => 'provider' + ] ]; public function __construct(App $app, array $services, array $routes, array $models, array $keys, int $authCount) @@ -86,8 +83,9 @@ abstract class Format * * Set param value * - * @param string $key - * @param string $value + * @param string $key + * @param string $value + * * @return self */ public function setParam(string $key, string $value): self @@ -102,8 +100,9 @@ abstract class Format * * Get param value * - * @param string $key - * @param string $default + * @param string $key + * @param string $default + * * @return string */ public function getParam(string $key, string $default = ''): string @@ -178,10 +177,8 @@ abstract class Format } break; } - return null; } - public function getEnumKeys(string $service, string $method, string $param): array { $values = []; @@ -193,21 +190,18 @@ abstract class Format foreach ($codes as $code => $value) { $values[] = $value['name']; } - return $values; case 'getCreditCard': $codes = Config::getParam('avatar-credit-cards'); foreach ($codes as $code => $value) { $values[] = $value['name']; } - return $values; case 'getFlag': $codes = Config::getParam('avatar-flags'); foreach ($codes as $code => $value) { $values[] = $value['name']; } - return $values; } break; @@ -217,8 +211,7 @@ abstract class Format case 'getCollectionUsage': case 'getDatabaseUsage': // Range Enum Keys - $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; - + $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; return $values; } break; @@ -228,7 +221,6 @@ abstract class Format case 'getFunctionUsage': // Range Enum Keys $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; - return $values; } break; @@ -239,7 +231,6 @@ abstract class Format // Range Enum Keys if ($param == 'range') { $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; - return $values; } } @@ -250,11 +241,9 @@ abstract class Format case 'getBucketUsage': // Range Enum Keys $values = ['Twenty Four Hours', 'Seven Days', 'Thirty Days', 'Ninety Days']; - return $values; } } - return $values; } } diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index f979ca1b4d..94cb0bb90d 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -20,32 +20,30 @@ class OpenAPI3 extends Format protected function getNestedModels(Model $model, array &$usedModels): void { foreach ($model->getRules() as $rule) { - if (! in_array($model->getType(), $usedModels)) { + if (!in_array($model->getType(), $usedModels)) { continue; } if (\is_array($rule['type'])) { foreach ($rule['type'] as $ruleType) { - if (! in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { + if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { $usedModels[] = $ruleType; foreach ($this->models as $m) { if ($m->getType() === $ruleType) { $this->getNestedModels($m, $usedModels); - continue; } } } } } else { - if (! in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { + if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])) { $usedModels[] = $rule['type']; foreach ($this->models as $m) { if ($m->getType() === $rule['type']) { $this->getNestedModels($m, $usedModels); - continue; } } @@ -127,7 +125,7 @@ class OpenAPI3 extends Format } $id = $route->getLabel('sdk.method', \uniqid()); - $desc = (! empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null; + $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; $produces = $route->getLabel('sdk.response.type', null); $model = $route->getLabel('sdk.response.model', 'none'); $routeSecurity = $route->getLabel('sdk.auth', []); @@ -156,7 +154,7 @@ class OpenAPI3 extends Format $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id), + 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), 'tags' => [$route->getLabel('sdk.namespace', 'default')], 'description' => ($desc) ? \file_get_contents($desc) : '', 'responses' => [], @@ -165,8 +163,8 @@ class OpenAPI3 extends Format 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), 'type' => $route->getLabel('sdk.methodType', ''), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master'.$route->getLabel('sdk.description', ''), + 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($id) . '.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), @@ -190,8 +188,8 @@ class OpenAPI3 extends Format } } - if (! (\is_array($model)) && $model->isNone()) { - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ + if (!(\is_array($model)) && $model->isNone()) { + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => in_array($produces, [ 'image/*', 'image/jpeg', @@ -205,19 +203,19 @@ class OpenAPI3 extends Format ]; } else { if (\is_array($model)) { - $modelDescription = \implode(', or ', \array_map(fn ($m) => $m->getName(), $model)); + $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); // model has multiple possible responses, we will use oneOf foreach ($model as $m) { $usedModels[] = $m->getType(); } - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $modelDescription, 'content' => [ $produces => [ 'schema' => [ - 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/'.$m->getType()], $model), + 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model) ], ], ], @@ -225,12 +223,12 @@ class OpenAPI3 extends Format } else { // Response definition using one type $usedModels[] = $model->getType(); - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'content' => [ $produces => [ 'schema' => [ - '$ref' => '#/components/schemas/'.$model->getType(), + '$ref' => '#/components/schemas/' . $model->getType(), ], ], ], @@ -239,11 +237,11 @@ class OpenAPI3 extends Format } if ($route->getLabel('sdk.response.code', 500) === 204) { - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['schema']); + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; + unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); } - if ((! empty($scope))) { // && 'public' != $scope + if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; foreach ($route->getLabel('sdk.auth', []) as $security) { @@ -258,8 +256,8 @@ class OpenAPI3 extends Format $body = [ 'content' => [ - $consumes[0] => [ - 'schema' => [ + $consumes[0] => [ + 'schema' => [ 'type' => 'object', 'properties' => [], ], @@ -278,7 +276,7 @@ class OpenAPI3 extends Format $node = [ 'name' => $name, 'description' => $param['description'], - 'required' => ! $param['optional'], + 'required' => !$param['optional'], ]; foreach ($this->services as $service) { @@ -294,10 +292,10 @@ class OpenAPI3 extends Format $validator = $validator->getValidator(); } - switch ((! empty($validator)) ? \get_class($validator) : '') { + switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Validator\Boolean': $node['schema']['type'] = $validator->getType(); @@ -305,14 +303,14 @@ class OpenAPI3 extends Format break; case 'Utopia\Database\Validator\UID': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Appwrite\Utopia\Database\Validator\CustomId': if ($route->getLabel('sdk.methodType', '') === 'upload') { $node['schema']['x-upload-id'] = true; } $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\DatetimeValidator': $node['schema']['type'] = $validator->getType(); @@ -369,14 +367,14 @@ class OpenAPI3 extends Format $node['schema']['items'] = [ 'type' => 'string', ]; - $node['schema']['x-example'] = '["'.Permission::read(Role::any()).'"]'; + $node['schema']['x-example'] = '["' . Permission::read(Role::any()) . '"]'; break; case 'Utopia\Database\Validator\Roles': $node['schema']['type'] = $validator->getType(); $node['schema']['items'] = [ 'type' => 'string', ]; - $node['schema']['x-example'] = '["'.Role::any()->toString().'"]'; + $node['schema']['x-example'] = '["' . Role::any()->toString() . '"]'; break; case 'Appwrite\Auth\Validator\Password': $node['schema']['type'] = $validator->getType(); @@ -431,9 +429,9 @@ class OpenAPI3 extends Format } if ($allowed) { - $node['schema']['enum'] = $validator->getList(); - $node['schema']['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); - $node['schema']['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); + $node['schema']['enum'] = $validator->getList(); + $node['schema']['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); + $node['schema']['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $route->getLabel('sdk.method', ''), $name); } if ($validator->getType() === 'integer') { $node['format'] = 'int32'; @@ -444,25 +442,25 @@ class OpenAPI3 extends Format break; } - if ($param['optional'] && ! \is_null($param['default'])) { // Param has default value + if ($param['optional'] && !\is_null($param['default'])) { // Param has default value $node['schema']['default'] = $param['default']; } - if (false !== \strpos($url, ':'.$name)) { // Param is in URL path + if (false !== \strpos($url, ':' . $name)) { // Param is in URL path $node['in'] = 'path'; $temp['parameters'][] = $node; } elseif ($route->getMethod() == 'GET') { // Param is in query $node['in'] = 'query'; $temp['parameters'][] = $node; } else { // Param is in payload - if (! $param['optional']) { + if (!$param['optional']) { $bodyRequired[] = $name; } $body['content'][$consumes[0]]['schema']['properties'][$name] = [ 'type' => $node['schema']['type'], 'description' => $node['description'], - 'x-example' => $node['schema']['x-example'] ?? null, + 'x-example' => $node['schema']['x-example'] ?? null ]; if (isset($node['schema']['enum'])) { @@ -493,14 +491,14 @@ class OpenAPI3 extends Format } } - $url = \str_replace(':'.$name, '{'.$name.'}', $url); + $url = \str_replace(':' . $name, '{' . $name . '}', $url); } - if (! empty($bodyRequired)) { + if (!empty($bodyRequired)) { $body['content'][$consumes[0]]['schema']['required'] = $bodyRequired; } - if (! empty($body['content'][$consumes[0]]['schema']['properties'])) { + if (!empty($body['content'][$consumes[0]]['schema']['properties'])) { $temp['requestBody'] = $body; } @@ -512,7 +510,7 @@ class OpenAPI3 extends Format } foreach ($this->models as $model) { - if (! in_array($model->getType(), $usedModels) && $model->getType() !== 'error') { + if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') { continue; } @@ -524,7 +522,7 @@ class OpenAPI3 extends Format 'type' => 'object', ]; - if (! empty($rules)) { + if (!empty($rules)) { $output['components']['schemas'][$model->getType()]['properties'] = []; } @@ -532,7 +530,7 @@ class OpenAPI3 extends Format $output['components']['schemas'][$model->getType()]['additionalProperties'] = true; } - if (! empty($required)) { + if (!empty($required)) { $output['components']['schemas'][$model->getType()]['required'] = $required; } @@ -579,19 +577,19 @@ class OpenAPI3 extends Format if ($rule['array']) { $items = [ 'anyOf' => \array_map(function ($type) { - return ['$ref' => '#/components/schemas/'.$type]; - }, $rule['type']), + return ['$ref' => '#/components/schemas/' . $type]; + }, $rule['type']) ]; } else { $items = [ 'oneOf' => \array_map(function ($type) { - return ['$ref' => '#/components/schemas/'.$type]; - }, $rule['type']), + return ['$ref' => '#/components/schemas/' . $type]; + }, $rule['type']) ]; } } else { $items = [ - '$ref' => '#/components/schemas/'.$rule['type'], + '$ref' => '#/components/schemas/' . $rule['type'], ]; } break; @@ -624,7 +622,7 @@ class OpenAPI3 extends Format if ($items) { $output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items; } - if (! in_array($name, $required)) { + if (!in_array($name, $required)) { $output['components']['schemas'][$model->getType()]['properties'][$name]['nullable'] = true; } } diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 15aad0238f..6b3d394aad 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -20,32 +20,30 @@ class Swagger2 extends Format protected function getNestedModels(Model $model, array &$usedModels): void { foreach ($model->getRules() as $rule) { - if (! in_array($model->getType(), $usedModels)) { + if (!in_array($model->getType(), $usedModels)) { continue; } if (\is_array($rule['type'])) { foreach ($rule['type'] as $ruleType) { - if (! in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) { + if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) { $usedModels[] = $ruleType; foreach ($this->models as $m) { if ($m->getType() === $ruleType) { $this->getNestedModels($m, $usedModels); - continue; } } } } } else { - if (! in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) { + if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) { $usedModels[] = $rule['type']; foreach ($this->models as $m) { if ($m->getType() === $rule['type']) { $this->getNestedModels($m, $usedModels); - continue; } } @@ -126,7 +124,7 @@ class Swagger2 extends Format } $id = $route->getLabel('sdk.method', \uniqid()); - $desc = (! empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null; + $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; $produces = $route->getLabel('sdk.response.type', null); $model = $route->getLabel('sdk.response.model', 'none'); $routeSecurity = $route->getLabel('sdk.auth', []); @@ -155,7 +153,7 @@ class Swagger2 extends Format $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id), + 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), 'consumes' => [], 'produces' => [], 'tags' => [$route->getLabel('sdk.namespace', 'default')], @@ -166,8 +164,8 @@ class Swagger2 extends Format 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), 'type' => $route->getLabel('sdk.methodType', ''), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master'.$route->getLabel('sdk.description', ''), + 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($id) . '.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), @@ -195,8 +193,8 @@ class Swagger2 extends Format } } - if (! (\is_array($model)) && $model->isNone()) { - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ + if (!(\is_array($model)) && $model->isNone()) { + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => in_array($produces, [ 'image/*', 'image/jpeg', @@ -208,42 +206,42 @@ class Swagger2 extends Format 'image/bmp', ]) ? 'Image' : 'File', 'schema' => [ - 'type' => 'file', + 'type' => 'file' ], ]; } else { if (\is_array($model)) { - $modelDescription = \implode(', or ', \array_map(fn ($m) => $m->getName(), $model)); + $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); // model has multiple possible responses, we will use oneOf foreach ($model as $m) { $usedModels[] = $m->getType(); } - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $modelDescription, 'schema' => [ 'x-oneOf' => \array_map(function ($m) { - return ['$ref' => '#/definitions/'.$m->getType()]; - }, $model), + return ['$ref' => '#/definitions/' . $m->getType()]; + }, $model) ], ]; } else { // Response definition using one type $usedModels[] = $model->getType(); - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')] = [ + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'schema' => [ - '$ref' => '#/definitions/'.$model->getType(), + '$ref' => '#/definitions/' . $model->getType(), ], ]; } } if (in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) { - $temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string) $route->getLabel('sdk.response.code', '500')]['schema']); + $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; + unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); } - if ((! empty($scope))) { // && 'public' != $scope + if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; foreach ($route->getLabel('sdk.auth', []) as $security) { @@ -279,7 +277,7 @@ class Swagger2 extends Format $node = [ 'name' => $name, 'description' => $param['description'], - 'required' => ! $param['optional'], + 'required' => !$param['optional'], ]; foreach ($this->services as $service) { @@ -295,10 +293,11 @@ class Swagger2 extends Format $validator = $validator->getValidator(); } - switch ((! empty($validator)) ? \get_class($validator) : '') { + + switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['type'] = $validator->getType(); - $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Validator\Boolean': $node['type'] = $validator->getType(); @@ -309,11 +308,11 @@ class Swagger2 extends Format $node['x-upload-id'] = true; } $node['type'] = $validator->getType(); - $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\UID': $node['type'] = $validator->getType(); - $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\DatetimeValidator': $node['type'] = $validator->getType(); @@ -370,7 +369,7 @@ class Swagger2 extends Format $node['items'] = [ 'type' => 'string', ]; - $node['x-example'] = '["'.Permission::read(Role::any()).'"]'; + $node['x-example'] = '["' . Permission::read(Role::any()) . '"]'; break; case 'Utopia\Database\Validator\Roles': $node['type'] = $validator->getType(); @@ -378,7 +377,7 @@ class Swagger2 extends Format $node['items'] = [ 'type' => 'string', ]; - $node['x-example'] = '["'.Role::any()->toString().'"]'; + $node['x-example'] = '["' . Role::any()->toString() . '"]'; break; case 'Appwrite\Auth\Validator\Password': $node['type'] = $validator->getType(); @@ -443,11 +442,11 @@ class Swagger2 extends Format break; } - if ($param['optional'] && ! \is_null($param['default'])) { // Param has default value + if ($param['optional'] && !\is_null($param['default'])) { // Param has default value $node['default'] = $param['default']; } - if (false !== \strpos($url, ':'.$name)) { // Param is in URL path + if (false !== \strpos($url, ':' . $name)) { // Param is in URL path $node['in'] = 'path'; $temp['parameters'][] = $node; } elseif ($route->getMethod() == 'GET') { // Param is in query @@ -461,7 +460,7 @@ class Swagger2 extends Format continue; } - if (! $param['optional']) { + if (!$param['optional']) { $bodyRequired[] = $name; } @@ -492,14 +491,14 @@ class Swagger2 extends Format } } - $url = \str_replace(':'.$name, '{'.$name.'}', $url); + $url = \str_replace(':' . $name, '{' . $name . '}', $url); } - if (! empty($bodyRequired)) { + if (!empty($bodyRequired)) { $body['schema']['required'] = $bodyRequired; } - if (! empty($body['schema']['properties'])) { + if (!empty($body['schema']['properties'])) { $temp['parameters'][] = $body; } @@ -513,7 +512,7 @@ class Swagger2 extends Format } foreach ($this->models as $model) { - if (! in_array($model->getType(), $usedModels)) { + if (!in_array($model->getType(), $usedModels)) { continue; } @@ -525,7 +524,7 @@ class Swagger2 extends Format 'type' => 'object', ]; - if (! empty($rules)) { + if (!empty($rules)) { $output['definitions'][$model->getType()]['properties'] = []; } @@ -533,7 +532,7 @@ class Swagger2 extends Format $output['definitions'][$model->getType()]['additionalProperties'] = true; } - if (! empty($required)) { + if (!empty($required)) { $output['definitions'][$model->getType()]['required'] = $required; } @@ -578,17 +577,17 @@ class Swagger2 extends Format if (\is_array($rule['type'])) { if ($rule['array']) { $items = [ - 'x-anyOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/'.$type], $rule['type']), + 'x-anyOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type']) ]; } else { $items = [ - 'x-oneOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/'.$type], $rule['type']), + 'x-oneOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type']) ]; } } else { $items = [ 'type' => $type, - '$ref' => '#/definitions/'.$rule['type'], + '$ref' => '#/definitions/' . $rule['type'], ]; } break; @@ -601,7 +600,6 @@ class Swagger2 extends Format 'description' => $rule['description'] ?? '', 'x-example' => $rule['example'] ?? null, ]; - continue; } @@ -632,7 +630,7 @@ class Swagger2 extends Format if ($items) { $output['definitions'][$model->getType()]['properties'][$name]['items'] = $items; } - if (! in_array($name, $required)) { + if (!in_array($name, $required)) { $output['definitions'][$model->getType()]['properties'][$name]['x-nullable'] = true; } } diff --git a/src/Appwrite/Task/Validator/Cron.php b/src/Appwrite/Task/Validator/Cron.php index a2709bc1c0..03bd1c5220 100644 --- a/src/Appwrite/Task/Validator/Cron.php +++ b/src/Appwrite/Task/Validator/Cron.php @@ -24,7 +24,8 @@ class Cron extends Validator * * Returns true if valid or false if not. * - * @param mixed $value + * @param mixed $value + * * @return bool */ public function isValid($value): bool @@ -33,7 +34,7 @@ class Cron extends Validator return true; } - if (! CronExpression::isValidExpression($value)) { + if (!CronExpression::isValidExpression($value)) { return false; } diff --git a/src/Appwrite/Template/Template.php b/src/Appwrite/Template/Template.php index 6b2bec0aef..c01d54389b 100644 --- a/src/Appwrite/Template/Template.php +++ b/src/Appwrite/Template/Template.php @@ -17,17 +17,18 @@ class Template extends View * * Creates a new Template() from the file at $path * - * @param string $path + * @param string $path + * * @return self + * */ public static function fromFile(string $path): self { - if (! \is_readable($path)) { + if (!\is_readable($path)) { throw new Exception("$path view template is not readable."); } $template = new Template(); - return $template->setPath($path); } @@ -36,8 +37,10 @@ class Template extends View * * Creates a new Template() using a raw string * - * @param string $content + * @param string $content + * * @return self + * */ public static function fromString(string $content): self { @@ -47,7 +50,6 @@ class Template extends View $template = new Template(); $template->content = $content; - return $template; } @@ -69,10 +71,10 @@ class Template extends View if (\is_readable($this->path)) { $template = \file_get_contents($this->path); // Include template file - } elseif (! empty($this->content)) { + } elseif (!empty($this->content)) { $template = $this->print($this->content, self::FILTER_NL2P); } else { - throw new Exception('"'.$this->path.'" template is not readable or not found'); + throw new Exception('"' . $this->path . '" template is not readable or not found'); } // First replace the variables inside the params. Then replace the variables in the template @@ -88,6 +90,7 @@ class Template extends View * Parse URL string to array * * @param $url + * * @return mixed On seriously malformed URLs, parse_url() may return FALSE. */ public static function parseURL($url) @@ -101,24 +104,25 @@ class Template extends View * Convert PHP array to query string * * @param $url + * * @return string */ public static function unParseURL(array $url) { - $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; + $scheme = isset($url['scheme']) ? $url['scheme'] . '://' : ''; $host = isset($url['host']) ? $url['host'] : ''; - $port = isset($url['port']) ? ':'.$url['port'] : ''; + $port = isset($url['port']) ? ':' . $url['port'] : ''; $user = isset($url['user']) ? $url['user'] : ''; - $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; + $pass = isset($url['pass']) ? ':' . $url['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; $path = isset($url['path']) ? $url['path'] : ''; - $query = isset($url['query']) && ! empty($url['query']) ? '?'.$url['query'] : ''; + $query = isset($url['query']) && !empty($url['query']) ? '?' . $url['query'] : ''; - $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; + $fragment = isset($url['fragment']) ? '#' . $url['fragment'] : ''; - return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; + return $scheme . $user . $pass . $host . $port . $path . $query . $fragment; } /** @@ -127,7 +131,8 @@ class Template extends View * Merge array of params to query string * * @param $query1 - * @param array $query2 + * @param array $query2 + * * @return string */ public static function mergeQuery($query1, array $query2) @@ -144,7 +149,7 @@ class Template extends View /** * From Camel Case * - * @var string + * @var string $input * * @return string */ @@ -162,7 +167,7 @@ class Template extends View /** * From Camel Case to Dash Case * - * @var string + * @var string $input * * @return string */ diff --git a/src/Appwrite/URL/URL.php b/src/Appwrite/URL/URL.php index bfc6b8ee7d..98250ab429 100644 --- a/src/Appwrite/URL/URL.php +++ b/src/Appwrite/URL/URL.php @@ -9,7 +9,8 @@ class URL * * Take a URL string and split it to array parts * - * @param string $url + * @param string $url + * * @return array */ public static function parse(string $url): array @@ -33,45 +34,46 @@ class URL * * Take URL parts and combine them to a valid string * - * @param array $url - * @param array $ommit + * @param array $url + * @param array $ommit + * * @return string */ public static function unparse(array $url, array $ommit = []): string { if (isset($url['path']) && \mb_substr($url['path'], 0, 1) !== '/') { - $url['path'] = '/'.$url['path']; + $url['path'] = '/' . $url['path']; } $parts = []; - $parts['scheme'] = isset($url['scheme']) ? $url['scheme'].'://' : ''; + $parts['scheme'] = isset($url['scheme']) ? $url['scheme'] . '://' : ''; $parts['host'] = isset($url['host']) ? $url['host'] : ''; - $parts['port'] = isset($url['port']) ? ':'.$url['port'] : ''; + $parts['port'] = isset($url['port']) ? ':' . $url['port'] : ''; $parts['user'] = isset($url['user']) ? $url['user'] : ''; - $parts['pass'] = isset($url['pass']) ? ':'.$url['pass'] : ''; + $parts['pass'] = isset($url['pass']) ? ':' . $url['pass'] : ''; - $parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'].'@' : ''; + $parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'] . '@' : ''; $parts['path'] = isset($url['path']) ? $url['path'] : ''; - $parts['query'] = isset($url['query']) && ! empty($url['query']) ? '?'.$url['query'] : ''; + $parts['query'] = isset($url['query']) && !empty($url['query']) ? '?' . $url['query'] : ''; - $parts['fragment'] = isset($url['fragment']) ? '#'.$url['fragment'] : ''; + $parts['fragment'] = isset($url['fragment']) ? '#' . $url['fragment'] : ''; if ($ommit) { foreach ($ommit as $key) { - if (isset($parts[$key])) { - $parts[$key] = ''; + if (isset($parts[ $key ])) { + $parts[ $key ] = ''; } } } - return $parts['scheme'].$parts['user'].$parts['pass'].$parts['host'].$parts['port'].$parts['path'].$parts['query'].$parts['fragment']; + return $parts['scheme'] . $parts['user'] . $parts['pass'] . $parts['host'] . $parts['port'] . $parts['path'] . $parts['query'] . $parts['fragment']; } /** @@ -79,7 +81,8 @@ class URL * * Convert query string to array * - * @param string $query + * @param string $query + * * @return array */ public static function parseQuery(string $query): array @@ -94,7 +97,8 @@ class URL * * Convert query string array to string * - * @param array $query + * @param array $query + * * @return string */ public static function unparseQuery(array $query): string diff --git a/src/Appwrite/Utopia/Database/Validator/CustomId.php b/src/Appwrite/Utopia/Database/Validator/CustomId.php index b6e913cb46..90d550371b 100644 --- a/src/Appwrite/Utopia/Database/Validator/CustomId.php +++ b/src/Appwrite/Utopia/Database/Validator/CustomId.php @@ -12,10 +12,12 @@ class CustomId extends Key * Returns true if valid or false if not. * * @param $value + * * @return bool */ public function isValid($value): bool { + return $value == 'unique()' || parent::isValid($value); } } diff --git a/src/Appwrite/Utopia/Database/Validator/ProjectId.php b/src/Appwrite/Utopia/Database/Validator/ProjectId.php index 482a74fc57..46b0cdf53e 100644 --- a/src/Appwrite/Utopia/Database/Validator/ProjectId.php +++ b/src/Appwrite/Utopia/Database/Validator/ProjectId.php @@ -12,6 +12,7 @@ class ProjectId extends Validator * Returns true if valid or false if not. * * @param $value + * * @return bool */ public function isValid($value): bool diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 86264df395..1463316ad1 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -2,6 +2,8 @@ namespace Appwrite\Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Select; + class Attributes extends Base { public const ALLOWED_ATTRIBUTES = [ @@ -11,11 +13,12 @@ class Attributes extends Base 'required', 'array', 'status', - 'error', + 'error' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index eca03206f9..3eea7b7b7e 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -2,24 +2,24 @@ namespace Appwrite\Utopia\Database\Validator\Queries; +use Appwrite\Extend\Exception; +use Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Limit; +use Utopia\Database\Validator\Query\Offset; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\Query\Filter; +use Utopia\Database\Validator\Query\Order; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Queries; -use Utopia\Database\Validator\Query\Cursor; -use Utopia\Database\Validator\Query\Filter; -use Utopia\Database\Validator\Query\Limit; -use Utopia\Database\Validator\Query\Offset; -use Utopia\Database\Validator\Query\Order; class Base extends Queries { /** * Expression constructor * - * @param string $collection - * @param string[] $allowedAttributes - * + * @param string $collection + * @param string[] $allowedAttributes * @throws \Exception */ public function __construct(string $collection, array $allowedAttributes) @@ -36,7 +36,7 @@ class Base extends Queries $attributes = []; foreach ($collection['attributes'] as $attribute) { $key = $attribute['$id']; - if (! isset($allowedAttributesLookup[$key])) { + if (!isset($allowedAttributesLookup[$key])) { continue; } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index 91d467b203..c4d187520f 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -10,11 +10,12 @@ class Buckets extends Base 'fileSecurity', 'maximumFileSize', 'encryption', - 'antivirus', + 'antivirus' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php index 9bf2381ed2..6e8fcb8339 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php @@ -7,11 +7,12 @@ class Collections extends Base public const ALLOWED_ATTRIBUTES = [ 'name', 'enabled', - 'documentSecurity', + 'documentSecurity' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php index e47d9020d1..22f7ad9b82 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php @@ -5,11 +5,12 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Databases extends Base { public const ALLOWED_ATTRIBUTES = [ - 'name', + 'name' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index 20fe9a7123..05b3326af1 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -13,6 +13,7 @@ class Deployments extends Base /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php index ca74367164..2bfe46e28d 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php @@ -8,11 +8,12 @@ class Executions extends Base 'trigger', 'status', 'statusCode', - 'duration', + 'duration' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php index 5984d32b9c..1941eabcdb 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php @@ -10,11 +10,12 @@ class Files extends Base 'mimeType', 'sizeOriginal', 'chunksTotal', - 'chunksUploaded', + 'chunksUploaded' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php index 77b7e14028..a2ba368953 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php @@ -12,11 +12,12 @@ class Functions extends Base 'schedule', 'scheduleNext', 'schedulePrevious', - 'timeout', + 'timeout' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php b/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php index 346c2f4799..cb0462ee13 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Identities.php @@ -14,6 +14,7 @@ class Identities extends Base /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php index 6ebf3cf50f..d9290e5737 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php @@ -14,6 +14,7 @@ class Indexes extends Base /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php index 73add15ac4..5ff0098662 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php @@ -9,11 +9,12 @@ class Memberships extends Base 'teamId', 'invited', 'joined', - 'confirm', + 'confirm' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php b/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php index 3cada3f633..6b9e9e6d32 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Migrations.php @@ -11,11 +11,12 @@ class Migrations extends Base 'resources', 'statusCounters', 'resourceData', - 'errors', + 'errors' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php b/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php index 6f36d73660..7fff26db7f 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Projects.php @@ -2,15 +2,18 @@ namespace Appwrite\Utopia\Database\Validator\Queries; +use Appwrite\Utopia\Database\Validator\Queries\Base; + class Projects extends Base { public const ALLOWED_ATTRIBUTES = [ 'name', - 'teamId', + 'teamId' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php index 00beab4e1d..83dbf665f1 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php @@ -12,6 +12,7 @@ class Providers extends Base /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php index ccc5fdbf7c..67aba71598 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php @@ -6,11 +6,12 @@ class Teams extends Base { public const ALLOWED_ATTRIBUTES = [ 'name', - 'total', + 'total' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php index b0fe844017..9b0dfe61e6 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php @@ -12,11 +12,12 @@ class Users extends Base 'passwordUpdate', 'registration', 'emailVerification', - 'phoneVerification', + 'phoneVerification' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php b/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php index 978c763b84..eff7007c58 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Variables.php @@ -2,14 +2,17 @@ namespace Appwrite\Utopia\Database\Validator\Queries; +use Appwrite\Utopia\Database\Validator\Queries\Base; + class Variables extends Base { public const ALLOWED_ATTRIBUTES = [ - 'key', + 'key' ]; /** * Expression constructor + * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 3f4d368e78..229c9dd53d 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -10,7 +10,6 @@ use Utopia\Swoole\Request as UtopiaRequest; class Request extends UtopiaRequest { private static ?Filter $filter = null; - private static ?Route $route = null; public function __construct(SwooleRequest $request) @@ -19,14 +18,14 @@ class Request extends UtopiaRequest } /** - * {@inheritdoc} + * @inheritdoc */ public function getParams(): array { $parameters = parent::getParams(); if (self::hasFilter() && self::hasRoute()) { - $endpointIdentifier = self::getRoute()->getLabel('sdk.namespace', 'unknown').'.'.self::getRoute()->getLabel('sdk.method', 'unknown'); + $endpointIdentifier = self::getRoute()->getLabel('sdk.namespace', 'unknown') . '.' . self::getRoute()->getLabel('sdk.method', 'unknown'); $parameters = self::getFilter()->parse($parameters, $endpointIdentifier); } @@ -36,7 +35,8 @@ class Request extends UtopiaRequest /** * Function to set a response filter * - * @param Filter|null $filter Filter the response filter to set + * @param Filter|null $filter Filter the response filter to set + * * @return void */ public static function setFilter(?Filter $filter): void @@ -67,7 +67,8 @@ class Request extends UtopiaRequest /** * Function to set a request route * - * @param Route|null $route the request route to set + * @param Route|null $route the request route to set + * * @return void */ public static function setRoute(?Route $route): void diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 4c1ea1bfd1..59346c7e17 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -7,8 +7,9 @@ abstract class Filter /** * Parse params to another format. * - * @param array $content - * @param string $model + * @param array $content + * @param string $model + * * @return array */ abstract public function parse(array $content, string $model): array; diff --git a/src/Appwrite/Utopia/Request/Filters/V12.php b/src/Appwrite/Utopia/Request/Filters/V12.php index 96fbf62885..f2a65307ae 100644 --- a/src/Appwrite/Utopia/Request/Filters/V12.php +++ b/src/Appwrite/Utopia/Request/Filters/V12.php @@ -11,44 +11,44 @@ class V12 extends Filter { switch ($model) { // No IDs -> Custom IDs - case 'account.create': - case 'account.createMagicURLSession': - case 'users.create': + case "account.create": + case "account.createMagicURLSession": + case "users.create": $content = $this->addId($content, 'userId'); break; - case 'functions.create': + case "functions.create": $content = $this->addId($content, 'functionId'); break; - case 'teams.create': + case "teams.create": $content = $this->addId($content, 'teamId'); break; - // Status integer -> boolean - case 'users.updateStatus': + // Status integer -> boolean + case "users.updateStatus": $content = $this->convertStatus($content); break; - // Deprecating order type - case 'functions.listExecutions': + // Deprecating order type + case "functions.listExecutions": $content = $this->removeOrderType($content); break; - // The rest (more complex) formats - case 'database.createDocument': + // The rest (more complex) formats + case "database.createDocument": $content = $this->addId($content, 'documentId'); $content = $this->removeParentProperties($content); break; - case 'database.listDocuments': + case "database.listDocuments": $content = $this->removeOrderCast($content); $content = $this->convertOrder($content); $content = $this->convertQueries($content); break; - case 'database.createCollection': + case "database.createCollection": $content = $this->addId($content, 'collectionId'); $content = $this->removeRules($content); $content = $this->addCollectionPermissionLevel($content); break; - case 'database.updateCollection': + case "database.updateCollection": $content = $this->removeRules($content); $content = $this->addCollectionPermissionLevel($content); break; @@ -62,14 +62,12 @@ class V12 extends Filter protected function addId(array $content, string $key): array { $content[$key] = 'unique()'; - return $content; } protected function addCollectionPermissionLevel(array $content): array { $content['permission'] = 'document'; - return $content; } @@ -78,21 +76,18 @@ class V12 extends Filter protected function removeRules(array $content): array { unset($content['rules']); - return $content; } protected function removeOrderType(array $content): array { unset($content['orderType']); - return $content; } protected function removeOrderCast(array $content): array { unset($content['orderCast']); - return $content; } @@ -107,7 +102,6 @@ class V12 extends Filter if (isset($content['parentPropertyType'])) { unset($content['parentPropertyType']); } - return $content; } @@ -118,19 +112,18 @@ class V12 extends Filter if (isset($content['status'])) { $content['status'] = $content['status'] === 2 ? false : true; } - return $content; } protected function convertOrder(array $content): array { if (isset($content['orderField'])) { - $content['orderAttributes'] = [$content['orderField']]; + $content['orderAttributes'] = [ $content['orderField'] ]; unset($content['orderField']); } if (isset($content['orderType'])) { - $content['orderTypes'] = [$content['orderType']]; + $content['orderTypes'] = [ $content['orderType'] ]; unset($content['orderType']); } @@ -141,7 +134,7 @@ class V12 extends Filter { $queries = []; - if (! empty($content['filters'])) { + if (!empty($content['filters'])) { foreach ($content['filters'] as $filter) { $operators = ['=' => 'equal', '!=' => 'notEqual', '>' => 'greater', '<' => 'lesser', '<=' => 'lesserEqual', '>=' => 'greaterEqual']; foreach ($operators as $operator => $operatorVerbose) { @@ -158,10 +151,10 @@ class V12 extends Filter // Let's keep it at true and false string, but without "" around // No action needed } else { - $filterValue = \is_numeric($filterValue) ? $filterValue : '"'.$filterValue.'"'; + $filterValue = \is_numeric($filterValue) ? $filterValue : '"' . $filterValue . '"'; } - $query = $attributeKey.'.'.$operators[$usedOperator].'('.$filterValue.')'; + $query = $attributeKey . '.' . $operators[$usedOperator] . '(' . $filterValue . ')'; \array_push($queries, $query); } } diff --git a/src/Appwrite/Utopia/Request/Filters/V13.php b/src/Appwrite/Utopia/Request/Filters/V13.php index 3f297b5943..e1122fdd71 100644 --- a/src/Appwrite/Utopia/Request/Filters/V13.php +++ b/src/Appwrite/Utopia/Request/Filters/V13.php @@ -11,13 +11,13 @@ class V13 extends Filter { switch ($model) { // Replaced Types - case 'database.createIntegerAttribute': - case 'database.createFloatAttribute': - $content = $this->convertStringToNum($content, 'min'); - $content = $this->convertStringToNum($content, 'max'); - $content = $this->convertStringToNum($content, 'default'); + case "database.createIntegerAttribute": + case "database.createFloatAttribute": + $content = $this->convertStringToNum($content, "min"); + $content = $this->convertStringToNum($content, "max"); + $content = $this->convertStringToNum($content, "default"); break; - case 'functions.createExecution': + case "functions.createExecution": $content = $this->convertExecution($content); } @@ -26,15 +26,13 @@ class V13 extends Filter private function convertStringToNum($content, $value) { - $content[$value] = is_null($content[$value]) ? null : (int) $content[$value]; - + $content[$value] = is_null($content[$value]) ? null : (int)$content[$value]; return $content; } private function convertExecution($content) { $content['async'] = true; - return $content; } } diff --git a/src/Appwrite/Utopia/Request/Filters/V14.php b/src/Appwrite/Utopia/Request/Filters/V14.php index 1b50404f82..7130307f0d 100644 --- a/src/Appwrite/Utopia/Request/Filters/V14.php +++ b/src/Appwrite/Utopia/Request/Filters/V14.php @@ -2,8 +2,8 @@ namespace Appwrite\Utopia\Request\Filters; -use Appwrite\Migration\Version\V13 as MigrationV13; use Appwrite\Utopia\Request\Filter; +use Appwrite\Migration\Version\V13 as MigrationV13; class V14 extends Filter { @@ -11,10 +11,10 @@ class V14 extends Filter public function parse(array $content, string $model): array { switch ($model) { - case 'functions.create': - case 'functions.update': - case 'projects.createWebhook': - case 'projects.updateWebhook': + case "functions.create": + case "functions.update": + case "projects.createWebhook": + case "projects.updateWebhook": $content = $this->convertEvents($content); break; } @@ -27,7 +27,7 @@ class V14 extends Filter $migration = new MigrationV13(); $events = $content['events'] ?? []; - $content['events'] = $migration->migrateEvents($events); + $content['events'] = $migration->migrateEvents($events); return $content; } diff --git a/src/Appwrite/Utopia/Request/Filters/V15.php b/src/Appwrite/Utopia/Request/Filters/V15.php index d535777350..318096fe0d 100644 --- a/src/Appwrite/Utopia/Request/Filters/V15.php +++ b/src/Appwrite/Utopia/Request/Filters/V15.php @@ -5,8 +5,8 @@ namespace Appwrite\Utopia\Request\Filters; use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; use Utopia\Database\Query; +use Utopia\Database\Helpers\Role; class V15 extends Filter { @@ -81,11 +81,11 @@ class V15 extends Filter protected function convertLimitAndOffset($content) { if (isset($content['limit'])) { - $content['queries'][] = 'limit('.$content['limit'].')'; + $content['queries'][] = 'limit(' . $content['limit'] . ')'; } if (isset($content['offset'])) { - $content['queries'][] = 'offset('.$content['offset'].')'; + $content['queries'][] = 'offset(' . $content['offset'] . ')'; } unset($content['limit']); @@ -100,9 +100,9 @@ class V15 extends Filter $cursorDirection = $content['cursorDirection'] ?? Database::CURSOR_AFTER; if ($cursorDirection === Database::CURSOR_BEFORE) { - $content['queries'][] = 'cursorBefore("'.$content['cursor'].'")'; + $content['queries'][] = 'cursorBefore("' . $content["cursor"] . '")'; } else { - $content['queries'][] = 'cursorAfter("'.$content['cursor'].'")'; + $content['queries'][] = 'cursorAfter("' . $content["cursor"] . '")'; } } @@ -133,9 +133,9 @@ class V15 extends Filter $attribute = $content['orderAttributes'][$i] ?? ''; if ($type === Database::ORDER_DESC) { - $content['queries'][] = 'orderDesc("'.$attribute.'")'; + $content['queries'][] = 'orderDesc("' . $attribute . '")'; } else { - $content['queries'][] = 'orderAsc("'.$attribute.'")'; + $content['queries'][] = 'orderAsc("' . $attribute . '")'; } } } @@ -194,7 +194,7 @@ class V15 extends Filter protected function convertFilters($content) { - if (! isset($content['queries'])) { + if (!isset($content['queries'])) { return $content; } @@ -214,19 +214,18 @@ class V15 extends Filter $parts = explode($middle, $query); if (count($parts) > 1) { $attribute = $parts[0]; - $value = rtrim($parts[1], ')'); - $content['queries'][$i] = $newOperation.'("'.$attribute.'", ['.$value.'])'; + $value = rtrim($parts[1], ")"); + $content['queries'][$i] = $newOperation . '("' . $attribute . '", [' . $value . '])'; } } } } - return $content; } protected function convertExecute($content) { - if (! isset($content['execute'])) { + if (!isset($content['execute'])) { return $content; } @@ -248,7 +247,7 @@ class V15 extends Filter protected function convertExpire($content) { - if (! isset($content['expire'])) { + if (!isset($content['expire'])) { return $content; } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 2954fc9d0d..952226a8d9 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -2,6 +2,14 @@ namespace Appwrite\Utopia; +use Appwrite\Utopia\Response\Model\Message; +use Appwrite\Utopia\Response\Model\Subscriber; +use Appwrite\Utopia\Response\Model\Topic; +use Exception; +use Swoole\Http\Request as SwooleRequest; +use Utopia\Swoole\Response as SwooleResponse; +use Swoole\Http\Response as SwooleHTTPResponse; +use Utopia\Database\Document; use Appwrite\Utopia\Response\Filter; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Account; @@ -12,72 +20,70 @@ use Appwrite\Utopia\Response\Model\AlgoPhpass; use Appwrite\Utopia\Response\Model\AlgoScrypt; use Appwrite\Utopia\Response\Model\AlgoScryptModified; use Appwrite\Utopia\Response\Model\AlgoSha; +use Appwrite\Utopia\Response\Model\None; use Appwrite\Utopia\Response\Model\Any; use Appwrite\Utopia\Response\Model\Attribute; +use Appwrite\Utopia\Response\Model\AttributeList; +use Appwrite\Utopia\Response\Model\AttributeString; +use Appwrite\Utopia\Response\Model\AttributeInteger; +use Appwrite\Utopia\Response\Model\AttributeFloat; use Appwrite\Utopia\Response\Model\AttributeBoolean; -use Appwrite\Utopia\Response\Model\AttributeDatetime; use Appwrite\Utopia\Response\Model\AttributeEmail; use Appwrite\Utopia\Response\Model\AttributeEnum; -use Appwrite\Utopia\Response\Model\AttributeFloat; -use Appwrite\Utopia\Response\Model\AttributeInteger; use Appwrite\Utopia\Response\Model\AttributeIP; -use Appwrite\Utopia\Response\Model\AttributeList; -use Appwrite\Utopia\Response\Model\AttributeRelationship; -use Appwrite\Utopia\Response\Model\AttributeString; use Appwrite\Utopia\Response\Model\AttributeURL; +use Appwrite\Utopia\Response\Model\AttributeDatetime; +use Appwrite\Utopia\Response\Model\AttributeRelationship; use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; -use Appwrite\Utopia\Response\Model\Bucket; -use Appwrite\Utopia\Response\Model\Build; use Appwrite\Utopia\Response\Model\Collection; -use Appwrite\Utopia\Response\Model\ConsoleVariables; +use Appwrite\Utopia\Response\Model\Database; use Appwrite\Utopia\Response\Model\Continent; use Appwrite\Utopia\Response\Model\Country; use Appwrite\Utopia\Response\Model\Currency; -use Appwrite\Utopia\Response\Model\Database; -use Appwrite\Utopia\Response\Model\Deployment; use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Domain; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; +use Appwrite\Utopia\Response\Model\Build; use Appwrite\Utopia\Response\Model\File; +use Appwrite\Utopia\Response\Model\Bucket; +use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Func; -use Appwrite\Utopia\Response\Model\HealthAntivirus; -use Appwrite\Utopia\Response\Model\HealthQueue; -use Appwrite\Utopia\Response\Model\HealthStatus; -use Appwrite\Utopia\Response\Model\HealthTime; -use Appwrite\Utopia\Response\Model\HealthVersion; use Appwrite\Utopia\Response\Model\Identity; use Appwrite\Utopia\Response\Model\Index; use Appwrite\Utopia\Response\Model\JWT; use Appwrite\Utopia\Response\Model\Key; use Appwrite\Utopia\Response\Model\Language; +use Appwrite\Utopia\Response\Model\User; +use Appwrite\Utopia\Response\Model\Session; +use Appwrite\Utopia\Response\Model\Team; use Appwrite\Utopia\Response\Model\Locale; -use Appwrite\Utopia\Response\Model\LocaleCode; use Appwrite\Utopia\Response\Model\Log; use Appwrite\Utopia\Response\Model\Membership; -use Appwrite\Utopia\Response\Model\Message; use Appwrite\Utopia\Response\Model\Metric; -use Appwrite\Utopia\Response\Model\Migration; -use Appwrite\Utopia\Response\Model\MigrationFirebaseProject; -use Appwrite\Utopia\Response\Model\MigrationReport; -use Appwrite\Utopia\Response\Model\Mock; -use Appwrite\Utopia\Response\Model\None; +use Appwrite\Utopia\Response\Model\Permissions; use Appwrite\Utopia\Response\Model\Phone; use Appwrite\Utopia\Response\Model\Platform; -use Appwrite\Utopia\Response\Model\Preferences; use Appwrite\Utopia\Response\Model\Project; +use Appwrite\Utopia\Response\Model\Rule; +use Appwrite\Utopia\Response\Model\Deployment; +use Appwrite\Utopia\Response\Model\TemplateEmail; +use Appwrite\Utopia\Response\Model\Token; +use Appwrite\Utopia\Response\Model\Webhook; +use Appwrite\Utopia\Response\Model\Preferences; +use Appwrite\Utopia\Response\Model\HealthAntivirus; +use Appwrite\Utopia\Response\Model\HealthQueue; +use Appwrite\Utopia\Response\Model\HealthStatus; +use Appwrite\Utopia\Response\Model\HealthTime; +use Appwrite\Utopia\Response\Model\HealthVersion; +use Appwrite\Utopia\Response\Model\LocaleCode; +use Appwrite\Utopia\Response\Model\Mock; // Keep last use Appwrite\Utopia\Response\Model\Provider; use Appwrite\Utopia\Response\Model\Runtime; -use Appwrite\Utopia\Response\Model\Session; -use Appwrite\Utopia\Response\Model\Subscriber; use Appwrite\Utopia\Response\Model\Target; -use Appwrite\Utopia\Response\Model\Team; -use Appwrite\Utopia\Response\Model\TemplateEmail; use Appwrite\Utopia\Response\Model\TemplateSMS; -use Appwrite\Utopia\Response\Model\Token; // Keep last -use Appwrite\Utopia\Response\Model\Topic; use Appwrite\Utopia\Response\Model\UsageBuckets; use Appwrite\Utopia\Response\Model\UsageCollection; use Appwrite\Utopia\Response\Model\UsageDatabase; @@ -87,13 +93,10 @@ use Appwrite\Utopia\Response\Model\UsageFunctions; use Appwrite\Utopia\Response\Model\UsageProject; use Appwrite\Utopia\Response\Model\UsageStorage; use Appwrite\Utopia\Response\Model\UsageUsers; -use Appwrite\Utopia\Response\Model\User; use Appwrite\Utopia\Response\Model\Variable; -use Appwrite\Utopia\Response\Model\Webhook; -use Exception; -use Swoole\Http\Response as SwooleHTTPResponse; -use Utopia\Database\Document; -use Utopia\Swoole\Response as SwooleResponse; +use Appwrite\Utopia\Response\Model\Migration; +use Appwrite\Utopia\Response\Model\MigrationFirebaseProject; +use Appwrite\Utopia\Response\Model\MigrationReport; /** * @method int getStatusCode() @@ -103,263 +106,152 @@ class Response extends SwooleResponse { // General public const MODEL_NONE = 'none'; - public const MODEL_ANY = 'any'; - public const MODEL_LOG = 'log'; - public const MODEL_LOG_LIST = 'logList'; - public const MODEL_ERROR = 'error'; - public const MODEL_METRIC = 'metric'; - public const MODEL_METRIC_LIST = 'metricList'; - public const MODEL_ERROR_DEV = 'errorDev'; - public const MODEL_BASE_LIST = 'baseList'; - public const MODEL_USAGE_DATABASES = 'usageDatabases'; - public const MODEL_USAGE_DATABASE = 'usageDatabase'; - public const MODEL_USAGE_COLLECTION = 'usageCollection'; - public const MODEL_USAGE_USERS = 'usageUsers'; - public const MODEL_USAGE_BUCKETS = 'usageBuckets'; - public const MODEL_USAGE_STORAGE = 'usageStorage'; - public const MODEL_USAGE_FUNCTIONS = 'usageFunctions'; - public const MODEL_USAGE_FUNCTION = 'usageFunction'; - public const MODEL_USAGE_PROJECT = 'usageProject'; // Database public const MODEL_DATABASE = 'database'; - public const MODEL_DATABASE_LIST = 'databaseList'; - public const MODEL_COLLECTION = 'collection'; - public const MODEL_COLLECTION_LIST = 'collectionList'; - public const MODEL_INDEX = 'index'; - public const MODEL_INDEX_LIST = 'indexList'; - public const MODEL_DOCUMENT = 'document'; - public const MODEL_DOCUMENT_LIST = 'documentList'; // Database Attributes public const MODEL_ATTRIBUTE = 'attribute'; - public const MODEL_ATTRIBUTE_LIST = 'attributeList'; - public const MODEL_ATTRIBUTE_STRING = 'attributeString'; - public const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger'; - public const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat'; - public const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean'; - public const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail'; - public const MODEL_ATTRIBUTE_ENUM = 'attributeEnum'; - public const MODEL_ATTRIBUTE_IP = 'attributeIp'; - public const MODEL_ATTRIBUTE_URL = 'attributeUrl'; - public const MODEL_ATTRIBUTE_DATETIME = 'attributeDatetime'; - public const MODEL_ATTRIBUTE_RELATIONSHIP = 'attributeRelationship'; // Users public const MODEL_ACCOUNT = 'account'; - public const MODEL_USER = 'user'; - public const MODEL_USER_LIST = 'userList'; - public const MODEL_SESSION = 'session'; - public const MODEL_SESSION_LIST = 'sessionList'; - public const MODEL_IDENTITY = 'identity'; - public const MODEL_IDENTITY_LIST = 'identityList'; - public const MODEL_TOKEN = 'token'; - public const MODEL_JWT = 'jwt'; - public const MODEL_PREFERENCES = 'preferences'; // Users password algos public const MODEL_ALGO_MD5 = 'algoMd5'; - public const MODEL_ALGO_SHA = 'algoSha'; - public const MODEL_ALGO_SCRYPT = 'algoScrypt'; - public const MODEL_ALGO_SCRYPT_MODIFIED = 'algoScryptModified'; - public const MODEL_ALGO_BCRYPT = 'algoBcrypt'; - public const MODEL_ALGO_ARGON2 = 'algoArgon2'; - public const MODEL_ALGO_PHPASS = 'algoPhpass'; // Storage public const MODEL_FILE = 'file'; - public const MODEL_FILE_LIST = 'fileList'; - public const MODEL_BUCKET = 'bucket'; - public const MODEL_BUCKET_LIST = 'bucketList'; // Locale public const MODEL_LOCALE = 'locale'; - public const MODEL_LOCALE_CODE = 'localeCode'; - public const MODEL_LOCALE_CODE_LIST = 'localeCodeList'; - public const MODEL_COUNTRY = 'country'; - public const MODEL_COUNTRY_LIST = 'countryList'; - public const MODEL_CONTINENT = 'continent'; - public const MODEL_CONTINENT_LIST = 'continentList'; - public const MODEL_CURRENCY = 'currency'; - public const MODEL_CURRENCY_LIST = 'currencyList'; - public const MODEL_LANGUAGE = 'language'; - public const MODEL_LANGUAGE_LIST = 'languageList'; - public const MODEL_PHONE = 'phone'; - public const MODEL_PHONE_LIST = 'phoneList'; // Messaging public const MODEL_PROVIDER = 'provider'; - public const MODEL_PROVIDER_LIST = 'providerList'; - public const MODEL_MESSAGE = 'message'; - public const MODEL_MESSAGE_LIST = 'messageList'; - public const MODEL_TOPIC = 'topic'; - public const MODEL_TOPIC_LIST = 'topicList'; - public const MODEL_SUBSCRIBER = 'subscriber'; - public const MODEL_SUBSCRIBER_LIST = 'subscriberList'; - public const MODEL_TARGET = 'target'; - public const MODEL_TARGET_LIST = 'targetList'; // Teams public const MODEL_TEAM = 'team'; - public const MODEL_TEAM_LIST = 'teamList'; - public const MODEL_MEMBERSHIP = 'membership'; - public const MODEL_MEMBERSHIP_LIST = 'membershipList'; // Functions public const MODEL_FUNCTION = 'function'; - public const MODEL_FUNCTION_LIST = 'functionList'; - public const MODEL_RUNTIME = 'runtime'; - public const MODEL_RUNTIME_LIST = 'runtimeList'; - public const MODEL_DEPLOYMENT = 'deployment'; - public const MODEL_DEPLOYMENT_LIST = 'deploymentList'; - public const MODEL_EXECUTION = 'execution'; - public const MODEL_EXECUTION_LIST = 'executionList'; - public const MODEL_BUILD = 'build'; - public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet - public const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; // Migrations public const MODEL_MIGRATION = 'migration'; - public const MODEL_MIGRATION_LIST = 'migrationList'; - public const MODEL_MIGRATION_REPORT = 'migrationReport'; - public const MODEL_MIGRATION_FIREBASE_PROJECT = 'firebaseProject'; - public const MODEL_MIGRATION_FIREBASE_PROJECT_LIST = 'firebaseProjectList'; // Project public const MODEL_PROJECT = 'project'; - public const MODEL_PROJECT_LIST = 'projectList'; - public const MODEL_WEBHOOK = 'webhook'; - public const MODEL_WEBHOOK_LIST = 'webhookList'; - public const MODEL_KEY = 'key'; - public const MODEL_KEY_LIST = 'keyList'; - public const MODEL_AUTH_PROVIDER = 'authProvider'; - public const MODEL_AUTH_PROVIDER_LIST = 'authProviderList'; - public const MODEL_PLATFORM = 'platform'; - public const MODEL_PLATFORM_LIST = 'platformList'; - public const MODEL_DOMAIN = 'domain'; - public const MODEL_DOMAIN_LIST = 'domainList'; - public const MODEL_VARIABLE = 'variable'; - public const MODEL_VARIABLE_LIST = 'variableList'; - public const MODEL_SMS_TEMPLATE = 'smsTemplate'; - public const MODEL_EMAIL_TEMPLATE = 'emailTemplate'; // Health public const MODEL_HEALTH_STATUS = 'healthStatus'; - public const MODEL_HEALTH_VERSION = 'healthVersion'; - public const MODEL_HEALTH_QUEUE = 'healthQueue'; - public const MODEL_HEALTH_TIME = 'healthTime'; - public const MODEL_HEALTH_ANTIVIRUS = 'healthAntivirus'; - public const MODEL_HEALTH_STATUS_LIST = 'healthStatusList'; // Console @@ -367,9 +259,7 @@ class Response extends SwooleResponse // Deprecated public const MODEL_PERMISSIONS = 'permissions'; - public const MODEL_RULE = 'rule'; - public const MODEL_TASK = 'task'; // Tests (keep last) @@ -388,7 +278,7 @@ class Response extends SwooleResponse /** * Response constructor. * - * @param float $time + * @param float $time */ public function __construct(SwooleHTTPResponse $response) { @@ -531,7 +421,6 @@ class Response extends SwooleResponse * HTTP content types */ public const CONTENT_TYPE_YAML = 'application/x-yaml'; - public const CONTENT_TYPE_NULL = 'null'; /** @@ -554,15 +443,14 @@ class Response extends SwooleResponse /** * Get Model Object * - * @param string $key + * @param string $key * @return Model - * * @throws Exception */ public function getModel(string $key): Model { - if (! isset($this->models[$key])) { - throw new Exception('Undefined model: '.$key); + if (!isset($this->models[$key])) { + throw new Exception('Undefined model: ' . $key); } return $this->models[$key]; @@ -582,11 +470,10 @@ class Response extends SwooleResponse * Validate response objects and outputs * the response according to given format type * - * @param Document $document - * @param string $model + * @param Document $document + * @param string $model * * return void - * * @throws Exception */ public function dynamic(Document $document, string $model): void @@ -600,11 +487,11 @@ class Response extends SwooleResponse switch ($this->getContentType()) { case self::CONTENT_TYPE_JSON: - $this->json(! empty($output) ? $output : new \stdClass()); + $this->json(!empty($output) ? $output : new \stdClass()); break; case self::CONTENT_TYPE_YAML: - $this->yaml(! empty($output) ? $output : new \stdClass()); + $this->yaml(!empty($output) ? $output : new \stdClass()); break; case self::CONTENT_TYPE_NULL: @@ -614,7 +501,7 @@ class Response extends SwooleResponse if ($model === self::MODEL_NONE) { $this->noContent(); } else { - $this->json(! empty($output) ? $output : new \stdClass()); + $this->json(!empty($output) ? $output : new \stdClass()); } break; } @@ -623,19 +510,18 @@ class Response extends SwooleResponse /** * Generate valid response object from document data * - * @param Document $document - * @param string $model + * @param Document $document + * @param string $model * * return array * @return array - * * @throws Exception */ public function output(Document $document, string $model): array { - $data = new Document($document->getArrayCopy()); - $model = $this->getModel($model); - $output = []; + $data = new Document($document->getArrayCopy()); + $model = $this->getModel($model); + $output = []; $data = $model->filter($document); @@ -646,17 +532,17 @@ class Response extends SwooleResponse } foreach ($model->getRules() as $key => $rule) { - if (! $document->isSet($key) && $rule['required']) { // do not set attribute in response if not required + if (!$document->isSet($key) && $rule['required']) { // do not set attribute in response if not required if (\array_key_exists('default', $rule)) { $data->setAttribute($key, $rule['default']); } else { - throw new Exception('Model '.$model->getName().' is missing response key: '.$key); + throw new Exception('Model ' . $model->getName() . ' is missing response key: ' . $key); } } if ($rule['array']) { - if (! is_array($document[$key])) { - throw new Exception($key.' must be an array of type '.$rule['type']); + if (!is_array($document[$key])) { + throw new Exception($key . ' must be an array of type ' . $rule['type']); } foreach ($document[$key] as $index => $item) { @@ -666,7 +552,7 @@ class Response extends SwooleResponse $condition = false; foreach ($this->getModel($type)->conditions as $attribute => $val) { $condition = $item->getAttribute($attribute) === $val; - if (! $condition) { + if (!$condition) { break; } } @@ -679,8 +565,8 @@ class Response extends SwooleResponse $ruleType = $rule['type']; } - if (! array_key_exists($ruleType, $this->models)) { - throw new Exception('Missing model for rule: '.$ruleType); + if (!array_key_exists($ruleType, $this->models)) { + throw new Exception('Missing model for rule: ' . $ruleType); } $data[$key][$index] = $this->output($item, $ruleType); @@ -705,13 +591,14 @@ class Response extends SwooleResponse * * Generate HTTP response output including the response header (+cookies) and body and prints them. * - * @param string $body + * @param string $body + * * @return void */ public function file(string $body = ''): void { $this->payload = [ - 'payload' => $body, + 'payload' => $body ]; $this->send($body); @@ -725,14 +612,14 @@ class Response extends SwooleResponse * * @see https://en.wikipedia.org/wiki/YAML * - * @param array $data - * @return void + * @param array $data * + * @return void * @throws Exception */ public function yaml(array $data): void { - if (! extension_loaded('yaml')) { + if (!extension_loaded('yaml')) { throw new Exception('Missing yaml extension. Learn more at: https://www.php.net/manual/en/book.yaml.php'); } @@ -753,6 +640,7 @@ class Response extends SwooleResponse * Function to set a response filter * * @param $filter the response filter to set + * * @return void */ public static function setFilter(?Filter $filter) diff --git a/src/Appwrite/Utopia/Response/Filter.php b/src/Appwrite/Utopia/Response/Filter.php index 47cca955fe..9110abd07a 100644 --- a/src/Appwrite/Utopia/Response/Filter.php +++ b/src/Appwrite/Utopia/Response/Filter.php @@ -7,8 +7,9 @@ abstract class Filter /** * Parse the content to another format. * - * @param array $content - * @param string $model + * @param array $content + * @param string $model + * * @return array */ abstract public function parse(array $content, string $model): array; diff --git a/src/Appwrite/Utopia/Response/Filters/V11.php b/src/Appwrite/Utopia/Response/Filters/V11.php index 09f9fbfc06..8fa22f42b2 100644 --- a/src/Appwrite/Utopia/Response/Filters/V11.php +++ b/src/Appwrite/Utopia/Response/Filters/V11.php @@ -42,7 +42,7 @@ class V11 extends Filter $parsedResponse = $this->parseFunctionsList($content); break; - // Convert status from boolean to int + // Convert status from boolean to int case Response::MODEL_USER: $parsedResponse = $this->parseStatus($content); break; @@ -50,7 +50,7 @@ class V11 extends Filter $parsedResponse = $this->parseUserList($content); break; - // Convert all Health responses back to original + // Convert all Health responses back to original case Response::MODEL_HEALTH_STATUS: $parsedResponse = $this->parseHealthStatus($content); break; @@ -67,7 +67,7 @@ class V11 extends Filter $parsedResponse = $this->parseHealthAntivirus($content); break; - // Complex filters + // Complex filters case Response::MODEL_COLLECTION: $parsedResponse = $this->parseCollection($content); break; @@ -101,7 +101,6 @@ class V11 extends Filter $parsedResponse[] = $this->parsePermissions($document); } $content['documents'] = $parsedResponse; - return $content; } @@ -113,7 +112,6 @@ class V11 extends Filter $parsedResponse[] = $this->parsePermissions($file); } $content['files'] = $parsedResponse; - return $content; } @@ -125,7 +123,6 @@ class V11 extends Filter $parsedResponse[] = $this->parseExecutionPermissions($execution); } $content['executions'] = $parsedResponse; - return $content; } @@ -137,7 +134,6 @@ class V11 extends Filter $parsedResponse[] = $this->parseFunctionPermissions($function); } $content['functions'] = $parsedResponse; - return $content; } @@ -149,7 +145,6 @@ class V11 extends Filter $parsedResponse[] = $this->parseStatus($user); } $content['users'] = $parsedResponse; - return $content; } @@ -164,7 +159,6 @@ class V11 extends Filter $parsedResponse = $this->addDate($content, 'dateCreated'); $parsedResponse = $this->addDate($content, 'dateUpdated'); $parsedResponse = $this->parseAttributes($content); - return $parsedResponse; } @@ -176,7 +170,6 @@ class V11 extends Filter $parsedResponse[] = $this->parseCollection($collection); } $content['collections'] = $parsedResponse; - return $content; } @@ -188,7 +181,6 @@ class V11 extends Filter $parsedResponse = $this->removeRule($content, 'userName'); $parsedResponse = $this->removeRule($content, 'mode'); $parsedResponse = $this->removeRule($content, 'sum'); - return $parsedResponse; } @@ -200,7 +192,6 @@ class V11 extends Filter $parsedResponse[] = $this->parseLog($log); } $content['logs'] = $parsedResponse; - return $content; } @@ -212,7 +203,6 @@ class V11 extends Filter $parsedResponse = $this->parseOAuths($content); $parsedResponse = $this->parseAuthsStatus($content); $parsedResponse = $this->removeServicesStatus($content); - return $parsedResponse; } @@ -224,7 +214,6 @@ class V11 extends Filter $parsedResponse[] = $this->parseProject($project); } $content['projects'] = $parsedResponse; - return $content; } @@ -259,6 +248,7 @@ class V11 extends Filter return $content; } + protected function parseHealthQueue(array $content) { // Did not change @@ -313,15 +303,15 @@ class V11 extends Filter protected function parseOAuths(array $content) { - $regexPattern = '/provider([a-zA-Z0-9]+)(Appid|Secret)/'; + $regexPattern = "/provider([a-zA-Z0-9]+)(Appid|Secret)/"; foreach ($content as $key => $value) { \preg_match_all($regexPattern, $key, $regexGroups); if (\count($regexGroups[1]) > 0 && \count($regexGroups[2]) > 0) { $providerName = $regexGroups[1][0]; $valueKey = $regexGroups[2][0]; - $content['usersOauth2'.$providerName.$valueKey] = $value; - unset($content['provider'.$providerName.$valueKey]); + $content['usersOauth2' . $providerName . $valueKey] = $value; + unset($content['provider' . $providerName . $valueKey]); } } @@ -330,7 +320,7 @@ class V11 extends Filter protected function parseAuthsStatus(array $content) { - $regexPattern = '/auth([a-zA-Z0-9]+)/'; + $regexPattern = "/auth([a-zA-Z0-9]+)/"; foreach ($content as $key => $value) { \preg_match_all($regexPattern, $key, $regexGroups); @@ -338,7 +328,7 @@ class V11 extends Filter $providerName = $regexGroups[1][0]; $content[$providerName] = $value; - unset($content['auth'.$providerName]); + unset($content['auth' . $providerName]); } } @@ -387,16 +377,15 @@ class V11 extends Filter protected function parsePermissions(array $content) { - $content['$permissions'] = ['read' => $content['$read'], 'write' => $content['$write']]; + $content['$permissions'] = [ 'read' => $content['$read'], 'write' => $content['$write'] ]; unset($content['$read']); unset($content['$write']); - return $content; } protected function parseFunctionPermissions(array $content) { - $content['$permissions'] = ['execute' => $content['execute']]; + $content['$permissions'] = [ 'execute' => $content['execute'] ]; unset($content['execute']); return $content; @@ -404,7 +393,7 @@ class V11 extends Filter protected function parseExecutionPermissions(array $content) { - $content['$permissions'] = ['read' => $content['$read']]; + $content['$permissions'] = [ 'read' => $content['$read'] ]; unset($content['$read']); return $content; diff --git a/src/Appwrite/Utopia/Response/Filters/V12.php b/src/Appwrite/Utopia/Response/Filters/V12.php index 795135bf43..79d22ad044 100644 --- a/src/Appwrite/Utopia/Response/Filters/V12.php +++ b/src/Appwrite/Utopia/Response/Filters/V12.php @@ -99,7 +99,6 @@ class V12 extends Filter protected function parseError(array $content) { unset($content['type']); - return $content; } @@ -125,7 +124,6 @@ class V12 extends Filter $content['sessions'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); - return $content; } @@ -148,7 +146,6 @@ class V12 extends Filter $content['files'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); - return $content; } @@ -156,7 +153,6 @@ class V12 extends Filter { $content['tag'] = $content['deployment']; unset($content['deployment']); - return $content; } @@ -170,7 +166,6 @@ class V12 extends Filter $content['functions'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); - return $content; } @@ -178,7 +173,6 @@ class V12 extends Filter { $content['functionId'] = $content['resourceId']; $content['command'] = $content['entrypoint']; - return $content; } @@ -192,14 +186,12 @@ class V12 extends Filter $content['deployments'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); - return $content; } protected function parseUsageBuckets(array $content) { unset($content['filesStorage']); - return $content; } @@ -245,7 +237,6 @@ class V12 extends Filter $content['executions'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); - return $content; } @@ -253,7 +244,6 @@ class V12 extends Filter { $content['sum'] = $content['total']; unset($content['total']); - return $content; } @@ -267,7 +257,6 @@ class V12 extends Filter $content['teams'] = $parsedResponse; $content['sum'] = $content['total']; unset($content['total']); - return $content; } @@ -275,7 +264,6 @@ class V12 extends Filter { $content['sum'] = $content['total']; unset($content['total']); - return $content; } } diff --git a/src/Appwrite/Utopia/Response/Filters/V13.php b/src/Appwrite/Utopia/Response/Filters/V13.php index 2c613280ac..d48473593e 100644 --- a/src/Appwrite/Utopia/Response/Filters/V13.php +++ b/src/Appwrite/Utopia/Response/Filters/V13.php @@ -55,7 +55,6 @@ class V13 extends Filter $parsedResponse[] = $this->parseExecution($document); } $content['executions'] = $parsedResponse; - return $content; } @@ -75,7 +74,6 @@ class V13 extends Filter $parsedResponse[] = $this->parseProject($document); } $content['projects'] = $parsedResponse; - return $content; } @@ -100,7 +98,6 @@ class V13 extends Filter $parsedResponse[] = $this->parseMembership($document); } $content['memberships'] = $parsedResponse; - return $content; } } diff --git a/src/Appwrite/Utopia/Response/Filters/V15.php b/src/Appwrite/Utopia/Response/Filters/V15.php index fadf426f1d..232feec201 100644 --- a/src/Appwrite/Utopia/Response/Filters/V15.php +++ b/src/Appwrite/Utopia/Response/Filters/V15.php @@ -210,13 +210,11 @@ class V15 extends Filter if (array_key_exists($attribute, $content)) { if (empty($content[$attribute])) { $content[$attribute] = 0; - continue; } $content[$attribute] = strtotime($content[$attribute]); } } - return $content; } @@ -227,20 +225,18 @@ class V15 extends Filter unset($content['hashOptions']); $content = $this->parseDatetimeAttributes($content, ['registration', 'passwordUpdate', '$createdAt', '$updatedAt']); - return $content; } protected function parseMetric(array $content) { $content = $this->parseDatetimeAttributes($content, ['date']); - return $content; } protected function parsePermissions(array $content) { - if (! isset($content['$permissions'])) { + if (!isset($content['$permissions'])) { return $content; } @@ -252,10 +248,10 @@ class V15 extends Filter $permission = Permission::parse($permission); $permission_value = $permission->getRole(); if ($permission->getIdentifier()) { - $permission_value .= ':'.$permission->getIdentifier(); + $permission_value .= ':' . $permission->getIdentifier(); } if ($permission->getDimension()) { - $permission_value .= '/'.$permission->getDimension(); + $permission_value .= '/' . $permission->getDimension(); } // Old type permissions meant that 'write' is equivalent to 'create', 'update' and 'delete' @@ -309,7 +305,6 @@ class V15 extends Filter unset($content['documentSecurity']); $content = $this->parsePermissions($content); $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); - return $content; } @@ -317,7 +312,6 @@ class V15 extends Filter { $content = $this->parsePermissions($content); $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); - return $content; } @@ -331,7 +325,6 @@ class V15 extends Filter unset($content['$databaseId']); $content = $this->parsePermissionsCreatedAtUpdatedAt($content); - return $content; } @@ -361,7 +354,6 @@ class V15 extends Filter private function parseCreatedAtUpdatedAt($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); - return $content; } @@ -394,28 +386,24 @@ class V15 extends Filter private function parseKey($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'expire']); - return $content; } private function parseLog($content) { $content = $this->parseDatetimeAttributes($content, ['time']); - return $content; } private function parseMembership($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'invited', 'joined']); - return $content; } private function parseSession($content) { $content = $this->parseDatetimeAttributes($content, ['$createdAt', 'expire', 'providerAccessTokenExpiry']); - return $content; } diff --git a/src/Appwrite/Utopia/Response/Model.php b/src/Appwrite/Utopia/Response/Model.php index 4aa4189248..8a0bb78cba 100644 --- a/src/Appwrite/Utopia/Response/Model.php +++ b/src/Appwrite/Utopia/Response/Model.php @@ -7,19 +7,12 @@ use Utopia\Database\Document; abstract class Model { public const TYPE_STRING = 'string'; - public const TYPE_INTEGER = 'integer'; - public const TYPE_FLOAT = 'double'; - public const TYPE_BOOLEAN = 'boolean'; - public const TYPE_JSON = 'json'; - public const TYPE_DATETIME = 'datetime'; - public const TYPE_DATETIME_EXAMPLE = '2020-10-15T06:38:00.000+00:00'; - public const TYPE_RELATIONSHIP = 'relationship'; /** @@ -47,6 +40,7 @@ abstract class Model */ public array $conditions = []; + /** * Filter Document Structure * @@ -85,8 +79,8 @@ abstract class Model * Add a New Rule * If rule is an array of documents with varying models * - * @param string $key - * @param array $options + * @param string $key + * @param array $options * @return Model */ protected function addRule(string $key, array $options): self @@ -95,7 +89,7 @@ abstract class Model 'required' => true, 'array' => false, 'description' => '', - 'example' => '', + 'example' => '' ], $options); return $this; @@ -105,7 +99,7 @@ abstract class Model * Delete an existing Rule * If rule exists, it will be removed * - * @param string $key + * @param string $key * @return Model */ protected function removeRule(string $key): self diff --git a/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php b/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php index ff2b0f94e0..3e162bb905 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php @@ -34,7 +34,8 @@ class AlgoArgon2 extends Model 'description' => 'Number of threads used to compute hash.', 'default' => '', 'example' => 3, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php b/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php index 066f976433..4dda297d71 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php @@ -39,7 +39,8 @@ class AlgoScrypt extends Model 'description' => 'Length used to compute hash.', 'default' => 64, 'example' => 64, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php b/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php index 73104eba7a..40b9df1dad 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php @@ -33,7 +33,8 @@ class AlgoScryptModified extends Model 'description' => 'Key used to compute hash.', 'default' => '', 'example' => 'XyEKE9RcTDeLEsL/RjwPDBv/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Attribute.php b/src/Appwrite/Utopia/Response/Model/Attribute.php index c7a014bd32..9f9ceca317 100644 --- a/src/Appwrite/Utopia/Response/Model/Attribute.php +++ b/src/Appwrite/Utopia/Response/Model/Attribute.php @@ -46,7 +46,8 @@ class Attribute extends Model 'default' => false, 'required' => false, 'example' => false, - ]); + ]) + ; } public array $conditions = []; diff --git a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php index e96140d0b3..05846817ca 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php @@ -28,12 +28,13 @@ class AttributeBoolean extends Attribute 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', 'default' => null, 'required' => false, - 'example' => false, - ]); + 'example' => false + ]) + ; } public array $conditions = [ - 'type' => self::TYPE_BOOLEAN, + 'type' => self::TYPE_BOOLEAN ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php b/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php index ccad8e7627..4651aebd06 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php @@ -37,11 +37,12 @@ class AttributeDatetime extends Attribute 'example' => self::TYPE_DATETIME_EXAMPLE, 'array' => false, 'required' => false, - ]); + ]) + ; } public array $conditions = [ - 'type' => self::TYPE_DATETIME, + 'type' => self::TYPE_DATETIME ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php index ffcdbc6eb1..078087dd4b 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php @@ -35,12 +35,13 @@ class AttributeEmail extends Attribute 'default' => null, 'required' => false, 'example' => 'default@example.com', - ]); + ]) + ; } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_EMAIL, + 'format' => \APP_DATABASE_ATTRIBUTE_EMAIL ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php index 0549c3cbe6..992b62ee3a 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php @@ -42,12 +42,13 @@ class AttributeEnum extends Attribute 'default' => null, 'required' => false, 'example' => 'element', - ]); + ]) + ; } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_ENUM, + 'format' => \APP_DATABASE_ATTRIBUTE_ENUM ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php index 28bd88e749..266b89c330 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php @@ -43,7 +43,8 @@ class AttributeFloat extends Attribute 'default' => null, 'required' => false, 'example' => 2.5, - ]); + ]) + ; } public array $conditions = [ diff --git a/src/Appwrite/Utopia/Response/Model/AttributeIP.php b/src/Appwrite/Utopia/Response/Model/AttributeIP.php index 2e746d735a..cfa309317a 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeIP.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeIP.php @@ -35,12 +35,13 @@ class AttributeIP extends Attribute 'default' => null, 'required' => false, 'example' => '192.0.2.0', - ]); + ]) + ; } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_IP, + 'format' => \APP_DATABASE_ATTRIBUTE_IP ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php index f672592553..fddfe57445 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php @@ -43,7 +43,8 @@ class AttributeInteger extends Attribute 'default' => null, 'required' => false, 'example' => 10, - ]); + ]) + ; } public array $conditions = [ @@ -52,7 +53,6 @@ class AttributeInteger extends Attribute /** * Get Name * - * * @return string */ public function getName(): string diff --git a/src/Appwrite/Utopia/Response/Model/AttributeList.php b/src/Appwrite/Utopia/Response/Model/AttributeList.php index b093dd7fe9..8b04475a14 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeList.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeList.php @@ -27,12 +27,13 @@ class AttributeList extends Model Response::MODEL_ATTRIBUTE_IP, Response::MODEL_ATTRIBUTE_DATETIME, Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute + Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute ], 'description' => 'List of attributes.', 'default' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php index 73b6a566f2..d88fbd1530 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php @@ -47,7 +47,8 @@ class AttributeRelationship extends Attribute 'description' => 'Whether this is the parent or child side of the relationship', 'default' => '', 'example' => 'parent|child', - ]); + ]) + ; } public array $conditions = [ @@ -82,7 +83,7 @@ class AttributeRelationship extends Attribute public function filter(Document $document): Document { $options = $document->getAttribute('options'); - if (! \is_null($options)) { + if (!\is_null($options)) { $document->setAttribute('relatedCollection', $options['relatedCollection']); $document->setAttribute('relationType', $options['relationType']); $document->setAttribute('twoWay', $options['twoWay']); @@ -90,7 +91,6 @@ class AttributeRelationship extends Attribute $document->setAttribute('side', $options['side']); $document->setAttribute('onDelete', $options['onDelete']); } - return $document; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index eb72d705e6..12bb42009d 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -23,7 +23,8 @@ class AttributeString extends Attribute 'default' => null, 'required' => false, 'example' => 'default', - ]); + ]) + ; } public array $conditions = [ diff --git a/src/Appwrite/Utopia/Response/Model/AttributeURL.php b/src/Appwrite/Utopia/Response/Model/AttributeURL.php index 78bd9c24d2..633d5b49d7 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeURL.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeURL.php @@ -35,12 +35,13 @@ class AttributeURL extends Attribute 'default' => null, 'required' => false, 'example' => 'http://example.com', - ]); + ]) + ; } public array $conditions = [ 'type' => self::TYPE_STRING, - 'format' => \APP_DATABASE_ATTRIBUTE_URL, + 'format' => \APP_DATABASE_ATTRIBUTE_URL ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/AuthProvider.php b/src/Appwrite/Utopia/Response/Model/AuthProvider.php index 840a2aa661..0171a3c152 100644 --- a/src/Appwrite/Utopia/Response/Model/AuthProvider.php +++ b/src/Appwrite/Utopia/Response/Model/AuthProvider.php @@ -43,7 +43,8 @@ class AuthProvider extends Model 'type' => self::TYPE_BOOLEAN, 'description' => 'Auth Provider is active and can be used to create session.', 'example' => '', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/BaseList.php b/src/Appwrite/Utopia/Response/Model/BaseList.php index cb0010a4e9..0c2cc072f3 100644 --- a/src/Appwrite/Utopia/Response/Model/BaseList.php +++ b/src/Appwrite/Utopia/Response/Model/BaseList.php @@ -17,12 +17,12 @@ class BaseList extends Model protected string $type = ''; /** - * @param string $name - * @param string $type - * @param string $key - * @param string $model - * @param bool $paging - * @param bool $public + * @param string $name + * @param string $type + * @param string $key + * @param string $model + * @param bool $paging + * @param bool $public */ public function __construct(string $name, string $type, string $key, string $model, bool $paging = true, bool $public = true) { @@ -34,13 +34,13 @@ class BaseList extends Model $namesWithCap = [ 'documents', 'collections', 'users', 'files', 'buckets', 'functions', 'deployments', 'executions', 'projects', 'webhooks', 'keys', - 'platforms', 'domains', 'memberships', 'teams', 'targets', + 'platforms', 'domains', 'memberships', 'teams', 'targets' ]; if (\in_array($name, $namesWithCap)) { - $description = 'Total number of '.$key.' documents that matched your query used as reference for offset pagination. When the `total` number of '.$key.' documents available is greater than 5000, total returned will be capped at 5000, and cursor pagination should be used. Read more about [pagination](https://appwrite.io/docs/pagination).'; + $description = 'Total number of ' . $key . ' documents that matched your query used as reference for offset pagination. When the `total` number of ' . $key . ' documents available is greater than 5000, total returned will be capped at 5000, and cursor pagination should be used. Read more about [pagination](https://appwrite.io/docs/pagination).'; } else { - $description = 'Total number of '.$key.' documents that matched your query.'; + $description = 'Total number of ' . $key . ' documents that matched your query.'; } $this->addRule('total', [ @@ -52,7 +52,7 @@ class BaseList extends Model } $this->addRule($key, [ 'type' => $model, - 'description' => 'List of '.$key.'.', + 'description' => 'List of ' . $key . '.', 'default' => [], 'array' => true, ]); diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index 16f1b02f24..0276c1d1f9 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -64,14 +64,14 @@ class Bucket extends Model 'description' => 'Allowed file extensions.', 'default' => [], 'example' => ['jpg', 'png'], - 'array' => true, + 'array' => true ]) ->addRule('compression', [ 'type' => self::TYPE_STRING, - 'description' => 'Compression algorithm choosen for compression. Will be one of '.COMPRESSION_TYPE_NONE.', ['.COMPRESSION_TYPE_GZIP.'](https://en.wikipedia.org/wiki/Gzip), or ['.COMPRESSION_TYPE_ZSTD.'](https://en.wikipedia.org/wiki/Zstd).', + 'description' => 'Compression algorithm choosen for compression. Will be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd).', 'default' => '', 'example' => 'gzip', - 'array' => false, + 'array' => false ]) ->addRule('encryption', [ 'type' => self::TYPE_BOOLEAN, @@ -84,7 +84,8 @@ class Bucket extends Model 'description' => 'Virus scanning is enabled.', 'default' => true, 'example' => false, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Build.php b/src/Appwrite/Utopia/Response/Model/Build.php index f8709bd027..b76f0ee083 100644 --- a/src/Appwrite/Utopia/Response/Model/Build.php +++ b/src/Appwrite/Utopia/Response/Model/Build.php @@ -62,7 +62,8 @@ class Build extends Model 'description' => 'The build duration in seconds.', 'default' => 0, 'example' => 0, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Collection.php b/src/Appwrite/Utopia/Response/Model/Collection.php index 2c876f2809..ae3e283378 100644 --- a/src/Appwrite/Utopia/Response/Model/Collection.php +++ b/src/Appwrite/Utopia/Response/Model/Collection.php @@ -33,7 +33,7 @@ class Collection extends Model 'description' => 'Collection permissions. [Learn more about permissions](/docs/permissions).', 'default' => '', 'example' => ['read("any")'], - 'array' => true, + 'array' => true ]) ->addRule('databaseId', [ 'type' => self::TYPE_STRING, @@ -82,8 +82,9 @@ class Collection extends Model 'description' => 'Collection indexes.', 'default' => [], 'example' => new \stdClass(), - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Continent.php b/src/Appwrite/Utopia/Response/Model/Continent.php index 4fd5c9e095..5291424a4a 100644 --- a/src/Appwrite/Utopia/Response/Model/Continent.php +++ b/src/Appwrite/Utopia/Response/Model/Continent.php @@ -21,7 +21,8 @@ class Continent extends Model 'description' => 'Continent two letter code.', 'default' => '', 'example' => 'EU', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Country.php b/src/Appwrite/Utopia/Response/Model/Country.php index 866460f929..64590a54d4 100644 --- a/src/Appwrite/Utopia/Response/Model/Country.php +++ b/src/Appwrite/Utopia/Response/Model/Country.php @@ -21,7 +21,8 @@ class Country extends Model 'description' => 'Country two-character ISO 3166-1 alpha code.', 'default' => '', 'example' => 'US', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Currency.php b/src/Appwrite/Utopia/Response/Model/Currency.php index e938f8a454..883ef486d8 100644 --- a/src/Appwrite/Utopia/Response/Model/Currency.php +++ b/src/Appwrite/Utopia/Response/Model/Currency.php @@ -51,7 +51,8 @@ class Currency extends Model 'description' => 'Currency plural name', 'default' => '', 'example' => 'US dollars', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Database.php b/src/Appwrite/Utopia/Response/Model/Database.php index 14e89419c3..bd9ae4625c 100644 --- a/src/Appwrite/Utopia/Response/Model/Database.php +++ b/src/Appwrite/Utopia/Response/Model/Database.php @@ -39,7 +39,8 @@ class Database extends Model 'description' => 'Database enabled.', 'default' => true, 'example' => false, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index be571810b8..8862d6a14e 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -87,7 +87,8 @@ class Deployment extends Model 'description' => 'The current build time in seconds.', 'default' => 0, 'example' => 128, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Domain.php b/src/Appwrite/Utopia/Response/Model/Domain.php index 9218a6fdf9..135bb52f90 100644 --- a/src/Appwrite/Utopia/Response/Model/Domain.php +++ b/src/Appwrite/Utopia/Response/Model/Domain.php @@ -62,7 +62,8 @@ class Domain extends Model 'description' => 'Certificate ID.', 'default' => '', 'example' => '6ejea5c13377e', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Error.php b/src/Appwrite/Utopia/Response/Model/Error.php index 6fc182214d..99cf3cbce2 100644 --- a/src/Appwrite/Utopia/Response/Model/Error.php +++ b/src/Appwrite/Utopia/Response/Model/Error.php @@ -33,7 +33,8 @@ class Error extends Model 'description' => 'Server version number.', 'default' => '', 'example' => '1.0', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/ErrorDev.php b/src/Appwrite/Utopia/Response/Model/ErrorDev.php index 4911da6bc7..9319397c77 100644 --- a/src/Appwrite/Utopia/Response/Model/ErrorDev.php +++ b/src/Appwrite/Utopia/Response/Model/ErrorDev.php @@ -34,7 +34,8 @@ class ErrorDev extends Error 'default' => [], 'example' => '', 'array' => true, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index d4bd212e93..8672a91598 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -83,7 +83,8 @@ class Execution extends Model 'description' => 'The script execution duration in seconds.', 'default' => 0, 'example' => 0.400, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/File.php b/src/Appwrite/Utopia/Response/Model/File.php index a9a89d2a41..53469f46b3 100644 --- a/src/Appwrite/Utopia/Response/Model/File.php +++ b/src/Appwrite/Utopia/Response/Model/File.php @@ -76,7 +76,8 @@ class File extends Model 'description' => 'Total number of chunks uploaded', 'default' => 0, 'example' => 17890, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index b3424b5e7c..c4044c0f2e 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -4,6 +4,8 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use stdClass; +use Utopia\Database\Document; class Func extends Model { @@ -64,7 +66,7 @@ class Func extends Model 'description' => 'Function variables.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('events', [ 'type' => self::TYPE_STRING, @@ -84,7 +86,8 @@ class Func extends Model 'description' => 'Function execution timeout in seconds.', 'default' => 15, 'example' => 15, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php b/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php index 97d608ff09..7a74195371 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php +++ b/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php @@ -21,7 +21,8 @@ class HealthAntivirus extends Model 'description' => 'Antivirus status. Possible values can are: `disabled`, `offline`, `online`', 'default' => '', 'example' => 'online', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthQueue.php b/src/Appwrite/Utopia/Response/Model/HealthQueue.php index 5990a4c5d3..da7c49a43f 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthQueue.php +++ b/src/Appwrite/Utopia/Response/Model/HealthQueue.php @@ -15,7 +15,8 @@ class HealthQueue extends Model 'description' => 'Amount of actions in the queue.', 'default' => 0, 'example' => 8, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthStatus.php b/src/Appwrite/Utopia/Response/Model/HealthStatus.php index 2bd8706763..ba340107ac 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthStatus.php +++ b/src/Appwrite/Utopia/Response/Model/HealthStatus.php @@ -27,7 +27,8 @@ class HealthStatus extends Model 'description' => 'Service status. Possible values can are: `pass`, `fail`', 'default' => '', 'example' => 'pass', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthTime.php b/src/Appwrite/Utopia/Response/Model/HealthTime.php index 0484b8ec33..042d073ce5 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthTime.php +++ b/src/Appwrite/Utopia/Response/Model/HealthTime.php @@ -27,7 +27,8 @@ class HealthTime extends Model 'description' => 'Difference of unix remote and local timestamps in milliseconds.', 'default' => 0, 'example' => 93, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/HealthVersion.php b/src/Appwrite/Utopia/Response/Model/HealthVersion.php index 6fab34576d..15a73c0e75 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthVersion.php +++ b/src/Appwrite/Utopia/Response/Model/HealthVersion.php @@ -15,7 +15,8 @@ class HealthVersion extends Model 'description' => 'Version of the Appwrite instance.', 'default' => '', 'example' => '0.11.0', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Identity.php b/src/Appwrite/Utopia/Response/Model/Identity.php index c23948acbf..ff7f57a3e6 100644 --- a/src/Appwrite/Utopia/Response/Model/Identity.php +++ b/src/Appwrite/Utopia/Response/Model/Identity.php @@ -69,7 +69,8 @@ class Identity extends Model 'description' => 'Identity Provider Refresh Token.', 'default' => '', 'example' => 'MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php index dcda9d11c6..3d3d1a3b52 100644 --- a/src/Appwrite/Utopia/Response/Model/Index.php +++ b/src/Appwrite/Utopia/Response/Model/Index.php @@ -48,7 +48,8 @@ class Index extends Model 'example' => [], 'array' => true, 'required' => false, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/JWT.php b/src/Appwrite/Utopia/Response/Model/JWT.php index debb81b28e..a2563a2ad8 100644 --- a/src/Appwrite/Utopia/Response/Model/JWT.php +++ b/src/Appwrite/Utopia/Response/Model/JWT.php @@ -14,7 +14,8 @@ class JWT extends Model 'type' => self::TYPE_STRING, 'description' => 'JWT encoded string.', 'example' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 1dba4e771b..1179a73d62 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -60,17 +60,18 @@ class Key extends Model ]) ->addRule('accessedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after '.APP_KEY_ACCCESS / 60 / 60 .' hours.', + 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after ' . APP_KEY_ACCCESS / 60 / 60 . ' hours.', 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, + 'example' => self::TYPE_DATETIME_EXAMPLE ]) ->addRule('sdks', [ 'type' => self::TYPE_STRING, 'description' => 'List of SDK user agents that used this key.', 'default' => null, 'example' => 'appwrite:flutter', - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Language.php b/src/Appwrite/Utopia/Response/Model/Language.php index c3f1072c82..64f99a006f 100644 --- a/src/Appwrite/Utopia/Response/Model/Language.php +++ b/src/Appwrite/Utopia/Response/Model/Language.php @@ -27,7 +27,8 @@ class Language extends Model 'description' => 'Language native name.', 'default' => '', 'example' => 'Italiano', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Locale.php b/src/Appwrite/Utopia/Response/Model/Locale.php index 61f371e7ac..fdfa363acd 100644 --- a/src/Appwrite/Utopia/Response/Model/Locale.php +++ b/src/Appwrite/Utopia/Response/Model/Locale.php @@ -51,7 +51,8 @@ class Locale extends Model 'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format', 'default' => '', 'example' => 'USD', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/LocaleCode.php b/src/Appwrite/Utopia/Response/Model/LocaleCode.php index d629c9a1a5..e73ceff6a5 100644 --- a/src/Appwrite/Utopia/Response/Model/LocaleCode.php +++ b/src/Appwrite/Utopia/Response/Model/LocaleCode.php @@ -21,7 +21,8 @@ class LocaleCode extends Model 'description' => 'Locale name', 'default' => '', 'example' => 'US', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Log.php b/src/Appwrite/Utopia/Response/Model/Log.php index 7177cad078..bc2c923494 100644 --- a/src/Appwrite/Utopia/Response/Model/Log.php +++ b/src/Appwrite/Utopia/Response/Model/Log.php @@ -135,7 +135,8 @@ class Log extends Model 'description' => 'Country name.', 'default' => '', 'example' => 'United States', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Membership.php b/src/Appwrite/Utopia/Response/Model/Membership.php index 2364ca5ec8..c134142185 100644 --- a/src/Appwrite/Utopia/Response/Model/Membership.php +++ b/src/Appwrite/Utopia/Response/Model/Membership.php @@ -82,7 +82,8 @@ class Membership extends Model 'default' => [], 'example' => ['owner'], 'array' => true, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Metric.php b/src/Appwrite/Utopia/Response/Model/Metric.php index 6b52f97e21..16cf7f7df2 100644 --- a/src/Appwrite/Utopia/Response/Model/Metric.php +++ b/src/Appwrite/Utopia/Response/Model/Metric.php @@ -20,7 +20,7 @@ class Metric extends Model 'type' => self::TYPE_DATETIME, 'description' => 'The date at which this metric was aggregated in ISO 8601 format.', 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, + 'example' => self::TYPE_DATETIME_EXAMPLE ]); } diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 33bccd23d2..78e8658032 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -51,7 +51,7 @@ class Migration extends Model 'description' => 'Resources to migration.', 'default' => [], 'example' => ['user'], - 'array' => true, + 'array' => true ]) ->addRule('statusCounters', [ 'type' => self::TYPE_JSON, @@ -70,7 +70,8 @@ class Migration extends Model 'description' => 'All errors that occurred during the migration process.', 'default' => [], 'example' => [], - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Mock.php b/src/Appwrite/Utopia/Response/Model/Mock.php index 7332e589f1..afdae66084 100644 --- a/src/Appwrite/Utopia/Response/Model/Mock.php +++ b/src/Appwrite/Utopia/Response/Model/Mock.php @@ -15,7 +15,8 @@ class Mock extends Model 'description' => 'Result message.', 'default' => '', 'example' => 'Success', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Phone.php b/src/Appwrite/Utopia/Response/Model/Phone.php index d732d0dc2e..226955919b 100644 --- a/src/Appwrite/Utopia/Response/Model/Phone.php +++ b/src/Appwrite/Utopia/Response/Model/Phone.php @@ -27,7 +27,8 @@ class Phone extends Model 'description' => 'Country name.', 'default' => '', 'example' => 'United States', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Platform.php b/src/Appwrite/Utopia/Response/Model/Platform.php index a25d819947..4b8ffb1486 100644 --- a/src/Appwrite/Utopia/Response/Model/Platform.php +++ b/src/Appwrite/Utopia/Response/Model/Platform.php @@ -73,7 +73,8 @@ class Platform extends Model 'description' => 'HTTP basic authentication password.', 'default' => '', 'example' => 'password', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Project.php b/src/Appwrite/Utopia/Response/Model/Project.php index 511952b142..35c3cf0e1f 100644 --- a/src/Appwrite/Utopia/Response/Model/Project.php +++ b/src/Appwrite/Utopia/Response/Model/Project.php @@ -178,7 +178,7 @@ class Project extends Model 'description' => 'Status for custom SMTP', 'default' => false, 'example' => false, - 'array' => false, + 'array' => false ]) ->addRule('smtpSender', [ 'type' => self::TYPE_STRING, @@ -215,7 +215,8 @@ class Project extends Model 'description' => 'SMTP server secure protocol', 'default' => '', 'example' => 'tls', - ]); + ]) + ; $services = Config::getParam('services', []); $auth = Config::getParam('auth', []); @@ -225,16 +226,17 @@ class Project extends Model $key = $method['key'] ?? ''; $this - ->addRule('auth'.ucfirst($key), [ + ->addRule('auth' . ucfirst($key), [ 'type' => self::TYPE_BOOLEAN, - 'description' => $name.' auth method status', + 'description' => $name . ' auth method status', 'example' => true, 'default' => true, - ]); + ]) + ; } foreach ($services as $service) { - if (! $service['optional']) { + if (!$service['optional']) { continue; } @@ -242,12 +244,13 @@ class Project extends Model $key = $service['key'] ?? ''; $this - ->addRule('serviceStatusFor'.ucfirst($key), [ + ->addRule('serviceStatusFor' . ucfirst($key), [ 'type' => self::TYPE_BOOLEAN, - 'description' => $name.' service status', + 'description' => $name . ' service status', 'example' => true, 'default' => true, - ]); + ]) + ; } } @@ -293,12 +296,12 @@ class Project extends Model $services = Config::getParam('services', []); foreach ($services as $service) { - if (! $service['optional']) { + if (!$service['optional']) { continue; } $key = $service['key'] ?? ''; $value = $values[$key] ?? true; - $document->setAttribute('serviceStatusFor'.ucfirst($key), $value); + $document->setAttribute('serviceStatusFor' . ucfirst($key), $value); } // Auth @@ -315,7 +318,7 @@ class Project extends Model foreach ($auth as $index => $method) { $key = $method['key']; $value = $authValues[$key] ?? true; - $document->setAttribute('auth'.ucfirst($key), $value); + $document->setAttribute('auth' . ucfirst($key), $value); } // Providers @@ -324,7 +327,7 @@ class Project extends Model $projectProviders = []; foreach ($providers as $key => $provider) { - if (! $provider['enabled']) { + if (!$provider['enabled']) { // Disabled by Appwrite configuration, exclude from response continue; } @@ -332,13 +335,13 @@ class Project extends Model $projectProviders[] = new Document([ 'key' => $key, 'name' => $provider['name'] ?? '', - 'appId' => $providerValues[$key.'Appid'] ?? '', - 'secret' => $providerValues[$key.'Secret'] ?? '', - 'enabled' => $providerValues[$key.'Enabled'] ?? false, + 'appId' => $providerValues[$key . 'Appid'] ?? '', + 'secret' => $providerValues[$key . 'Secret'] ?? '', + 'enabled' => $providerValues[$key . 'Enabled'] ?? false, ]); } - $document->setAttribute('providers', $projectProviders); + $document->setAttribute("providers", $projectProviders); return $document; } diff --git a/src/Appwrite/Utopia/Response/Model/Runtime.php b/src/Appwrite/Utopia/Response/Model/Runtime.php index 43cf711994..8bc42cb418 100644 --- a/src/Appwrite/Utopia/Response/Model/Runtime.php +++ b/src/Appwrite/Utopia/Response/Model/Runtime.php @@ -20,7 +20,7 @@ class Runtime extends Model 'type' => self::TYPE_STRING, 'description' => 'Runtime Name.', 'default' => '', - 'example' => 'Python', + 'example' => 'Python' ]) ->addRule('version', [ 'type' => self::TYPE_STRING, @@ -52,7 +52,8 @@ class Runtime extends Model 'default' => '', 'example' => 'amd64', 'array' => true, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Session.php b/src/Appwrite/Utopia/Response/Model/Session.php index 7b71780c4e..d961966b24 100644 --- a/src/Appwrite/Utopia/Response/Model/Session.php +++ b/src/Appwrite/Utopia/Response/Model/Session.php @@ -159,7 +159,8 @@ class Session extends Model 'description' => 'Returns true if this the current user session.', 'default' => false, 'example' => true, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Team.php b/src/Appwrite/Utopia/Response/Model/Team.php index e180afbbeb..d080a82bb1 100644 --- a/src/Appwrite/Utopia/Response/Model/Team.php +++ b/src/Appwrite/Utopia/Response/Model/Team.php @@ -46,7 +46,8 @@ class Team extends Model 'description' => 'Team preferences as a key-value object', 'default' => new \stdClass(), 'example' => ['theme' => 'pink', 'timezone' => 'UTC'], - ]); + ]) + ; } /** @@ -64,7 +65,6 @@ class Team extends Model if (is_array($prefs) && empty($prefs)) { $document->setAttribute('prefs', new \stdClass()); } - return $document; } diff --git a/src/Appwrite/Utopia/Response/Model/Template.php b/src/Appwrite/Utopia/Response/Model/Template.php index 9d4f81068a..3ce9cacdb3 100644 --- a/src/Appwrite/Utopia/Response/Model/Template.php +++ b/src/Appwrite/Utopia/Response/Model/Template.php @@ -26,6 +26,7 @@ abstract class Template extends Model 'description' => 'Template message', 'default' => '', 'example' => 'Click on the link to verify your account.', - ]); + ]) + ; } } diff --git a/src/Appwrite/Utopia/Response/Model/TemplateEmail.php b/src/Appwrite/Utopia/Response/Model/TemplateEmail.php index 1babef9f90..ecdf89e774 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateEmail.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateEmail.php @@ -33,7 +33,8 @@ class TemplateEmail extends Template 'description' => 'Email subject', 'default' => '', 'example' => 'Please verify your email address', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/TemplateSMS.php b/src/Appwrite/Utopia/Response/Model/TemplateSMS.php index f0abcdc511..2b19ef4878 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateSMS.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateSMS.php @@ -10,7 +10,6 @@ class TemplateSMS extends Template { parent::__construct(); } - /** * Get Name * diff --git a/src/Appwrite/Utopia/Response/Model/Token.php b/src/Appwrite/Utopia/Response/Model/Token.php index 05bbe10302..c409e37f03 100644 --- a/src/Appwrite/Utopia/Response/Model/Token.php +++ b/src/Appwrite/Utopia/Response/Model/Token.php @@ -39,7 +39,8 @@ class Token extends Model 'description' => 'Token expiration date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php index 1f708a0b4d..83b8744760 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php +++ b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php @@ -21,15 +21,16 @@ class UsageBuckets extends Model 'description' => 'Aggregated stats for total number of files in this bucket.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total storage of files in this bucket.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageCollection.php b/src/Appwrite/Utopia/Response/Model/UsageCollection.php index fd5350af86..5abcf46b7d 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageCollection.php +++ b/src/Appwrite/Utopia/Response/Model/UsageCollection.php @@ -21,8 +21,9 @@ class UsageCollection extends Model 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index fac50676a6..58d49c506e 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -21,15 +21,16 @@ class UsageDatabase extends Model 'description' => 'Aggregated stats for total number of collections.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index 20c2a1aecb..a6008ca9e6 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -21,22 +21,23 @@ class UsageDatabases extends Model 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('collectionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of collections.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunction.php b/src/Appwrite/Utopia/Response/Model/UsageFunction.php index 013bf4056d..03acaa750a 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunction.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunction.php @@ -21,42 +21,42 @@ class UsageFunction extends Model 'description' => 'Aggregated stats for number of function deployments.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('deploymentsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function deployments storage.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('buildsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function builds.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('buildsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for builds storage.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('buildsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function build compute.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function executions.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('executionsTime', [ @@ -64,8 +64,9 @@ class UsageFunction extends Model 'description' => 'Aggregated stats for function execution compute.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php index 003f6390ad..6ab36e21ac 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php @@ -21,49 +21,49 @@ class UsageFunctions extends Model 'description' => 'Aggregated stats for number of functions.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('deploymentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function deployments.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('deploymentsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function deployments storage.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('buildsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function builds.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('buildsStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for builds storage.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('buildsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function build compute.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function executions.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('executionsTime', [ @@ -71,8 +71,9 @@ class UsageFunctions extends Model 'description' => 'Aggregated stats for function execution compute.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 41acef102f..641613809a 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -21,57 +21,58 @@ class UsageProject extends Model 'description' => 'Aggregated stats for number of requests.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('network', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for consumed bandwidth.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function executions.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of documents.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('databasesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of databases.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('usersTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of users.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('bucketsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of buckets.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageStorage.php b/src/Appwrite/Utopia/Response/Model/UsageStorage.php index 4d83948fb8..88d0beca01 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageStorage.php +++ b/src/Appwrite/Utopia/Response/Model/UsageStorage.php @@ -21,22 +21,23 @@ class UsageStorage extends Model 'description' => 'Aggregated stats for total number of buckets.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('filesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of files.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/UsageUsers.php b/src/Appwrite/Utopia/Response/Model/UsageUsers.php index 71774bf61d..c0cc4baa54 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageUsers.php +++ b/src/Appwrite/Utopia/Response/Model/UsageUsers.php @@ -21,7 +21,7 @@ class UsageUsers extends Model 'description' => 'Aggregated stats for total number of users.', 'default' => [], 'example' => [], - 'array' => true, + 'array' => true ]) ->addRule('sessionsTotal', [ @@ -29,8 +29,9 @@ class UsageUsers extends Model 'description' => 'Aggregated stats for sessions created.', 'default' => [], 'example' => [], - 'array' => true, - ]); + 'array' => true + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/User.php b/src/Appwrite/Utopia/Response/Model/User.php index a69c30f9d1..d6988b47f4 100644 --- a/src/Appwrite/Utopia/Response/Model/User.php +++ b/src/Appwrite/Utopia/Response/Model/User.php @@ -129,10 +129,11 @@ class User extends Model ]) ->addRule('accessedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after '.APP_USER_ACCCESS / 60 / 60 .' hours.', + 'description' => 'Most recent access date in ISO 8601 format. This attribute is only updated again after ' . APP_USER_ACCCESS / 60 / 60 . ' hours.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, - ]); + ]) + ; } /** @@ -150,7 +151,6 @@ class User extends Model if (is_array($prefs) && empty($prefs)) { $document->setAttribute('prefs', new \stdClass()); } - return $document; } diff --git a/src/Appwrite/Utopia/Response/Model/Variable.php b/src/Appwrite/Utopia/Response/Model/Variable.php index 7d84e8803f..f4b3bcf2bb 100644 --- a/src/Appwrite/Utopia/Response/Model/Variable.php +++ b/src/Appwrite/Utopia/Response/Model/Variable.php @@ -46,7 +46,8 @@ class Variable extends Model 'description' => 'Function ID.', 'default' => '', 'example' => '5e5ea5c16897e', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/Response/Model/Webhook.php b/src/Appwrite/Utopia/Response/Model/Webhook.php index d9e0f4be3c..781bb9186d 100644 --- a/src/Appwrite/Utopia/Response/Model/Webhook.php +++ b/src/Appwrite/Utopia/Response/Model/Webhook.php @@ -75,7 +75,8 @@ class Webhook extends Model 'description' => 'Signature key which can be used to validated incoming', 'default' => '', 'example' => 'ad3d581ca230e2b7059c545e5a', - ]); + ]) + ; } /** diff --git a/src/Appwrite/Utopia/View.php b/src/Appwrite/Utopia/View.php index ba0a1f0fc6..e4ed8164c9 100644 --- a/src/Appwrite/Utopia/View.php +++ b/src/Appwrite/Utopia/View.php @@ -11,9 +11,8 @@ class View extends OldView * * Convert all applicable characters to HTML entities * - * @param string $str + * @param string $str * @return string - * * @deprecated Use print method with escape filter */ public function escape($str) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 4e158eb362..bd49e5cf20 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -8,21 +8,13 @@ use Utopia\App; class Executor { public const METHOD_GET = 'GET'; - public const METHOD_POST = 'POST'; - public const METHOD_PUT = 'PUT'; - public const METHOD_PATCH = 'PATCH'; - public const METHOD_DELETE = 'DELETE'; - public const METHOD_HEAD = 'HEAD'; - public const METHOD_OPTIONS = 'OPTIONS'; - public const METHOD_CONNECT = 'CONNECT'; - public const METHOD_TRACE = 'TRACE'; private bool $selfSigned = false; @@ -37,7 +29,7 @@ class Executor public function __construct(string $endpoint) { - if (! filter_var($endpoint, FILTER_VALIDATE_URL)) { + if (!filter_var($endpoint, FILTER_VALIDATE_URL)) { throw new Exception('Unsupported endpoint'); } @@ -46,7 +38,7 @@ class Executor $this->memory = intval(App::getEnv('_APP_FUNCTIONS_MEMORY', '512')); $this->headers = [ 'content-type' => 'application/json', - 'authorization' => 'Bearer '.App::getEnv('_APP_EXECUTOR_SECRET', ''), + 'authorization' => 'Bearer ' . App::getEnv('_APP_EXECUTOR_SECRET', ''), ]; } @@ -55,16 +47,16 @@ class Executor * * Launches a runtime container for a deployment ready for execution * - * @param string $deploymentId - * @param string $projectId - * @param string $source - * @param string $image - * @param bool $remove - * @param string $entrypoint - * @param string $workdir - * @param string $destination - * @param array $variables - * @param array $commands + * @param string $deploymentId + * @param string $projectId + * @param string $source + * @param string $image + * @param bool $remove + * @param string $entrypoint + * @param string $workdir + * @param string $destination + * @param array $variables + * @param array $commands */ public function createRuntime( string $deploymentId, @@ -79,8 +71,8 @@ class Executor array $commands = [] ) { $runtimeId = "$projectId-$deploymentId"; - $route = '/runtimes'; - $headers = ['x-opr-runtime-id' => $runtimeId]; + $route = "/runtimes"; + $headers = [ 'x-opr-runtime-id' => $runtimeId ]; $params = [ 'runtimeId' => $runtimeId, 'source' => $source, @@ -95,7 +87,7 @@ class Executor 'memory' => $this->memory, ]; - $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); + $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $timeout); @@ -111,14 +103,15 @@ class Executor /** * Create an execution * - * @param string $projectId - * @param string $deploymentId - * @param string $payload - * @param array $variables - * @param int $timeout - * @param string $image - * @param string $source - * @param string $entrypoint + * @param string $projectId + * @param string $deploymentId + * @param string $payload + * @param array $variables + * @param int $timeout + * @param string $image + * @param string $source + * @param string $entrypoint + * * @return array */ public function createExecution( @@ -132,8 +125,8 @@ class Executor string $entrypoint, ) { $runtimeId = "$projectId-$deploymentId"; - $route = '/runtimes/'.$runtimeId.'/execution'; - $headers = ['x-opr-runtime-id' => $runtimeId]; + $route = '/runtimes/' . $runtimeId . '/execution'; + $headers = [ 'x-opr-runtime-id' => $runtimeId ]; $params = [ 'runtimeId' => $runtimeId, 'variables' => $variables, @@ -147,7 +140,7 @@ class Executor 'memory' => $this->memory, ]; - $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); + $timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $timeout); @@ -165,23 +158,22 @@ class Executor * * Make an API call * - * @param string $method - * @param string $path - * @param array $params - * @param array $headers - * @param bool $decode + * @param string $method + * @param string $path + * @param array $params + * @param array $headers + * @param bool $decode * @return array|string - * * @throws Exception */ public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15) { - $headers = array_merge($this->headers, $headers); - $ch = curl_init($this->endpoint.$path.(($method == self::METHOD_GET && ! empty($params)) ? '?'.http_build_query($params) : '')); - $responseHeaders = []; - $responseStatus = -1; - $responseType = ''; - $responseBody = ''; + $headers = array_merge($this->headers, $headers); + $ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); + $responseHeaders = []; + $responseStatus = -1; + $responseType = ''; + $responseBody = ''; switch ($headers['content-type']) { case 'application/json': @@ -198,7 +190,7 @@ class Executor } foreach ($headers as $i => $header) { - $headers[] = $i.':'.$header; + $headers[] = $i . ':' . $header; unset($headers[$i]); } @@ -231,8 +223,8 @@ class Executor curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - $responseBody = curl_exec($ch); - $responseType = $responseHeaders['content-type'] ?? ''; + $responseBody = curl_exec($ch); + $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($decode) { @@ -241,7 +233,7 @@ class Executor $json = json_decode($responseBody, true); if ($json === null) { - throw new Exception('Failed to parse response: '.$responseBody); + throw new Exception('Failed to parse response: ' . $responseBody); } $responseBody = $json; @@ -251,7 +243,7 @@ class Executor } if ((curl_errno($ch)/* || 200 != $responseStatus*/)) { - throw new Exception(curl_error($ch).' with status code '.$responseStatus, $responseStatus); + throw new Exception(curl_error($ch) . ' with status code ' . $responseStatus, $responseStatus); } curl_close($ch); @@ -260,21 +252,21 @@ class Executor return [ 'headers' => $responseHeaders, - 'body' => $responseBody, + 'body' => $responseBody ]; } /** * Parse Cookie String * - * @param string $cookie + * @param string $cookie * @return array */ public function parseCookie(string $cookie): array { $cookies = []; - parse_str(strtr($cookie, ['&' => '%26', '+' => '%2B', ';' => '&']), $cookies); + parse_str(strtr($cookie, array('&' => '%26', '+' => '%2B', ';' => '&')), $cookies); return $cookies; } @@ -282,8 +274,8 @@ class Executor /** * Flatten params array to PHP multiple format * - * @param array $data - * @param string $prefix + * @param array $data + * @param string $prefix * @return array */ protected function flatten(array $data, string $prefix = ''): array diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index 6a9176232b..21e4ccc958 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -7,21 +7,13 @@ use Exception; class Client { public const METHOD_GET = 'GET'; - public const METHOD_POST = 'POST'; - public const METHOD_PUT = 'PUT'; - public const METHOD_PATCH = 'PATCH'; - public const METHOD_DELETE = 'DELETE'; - public const METHOD_HEAD = 'HEAD'; - public const METHOD_OPTIONS = 'OPTIONS'; - public const METHOD_CONNECT = 'CONNECT'; - public const METHOD_TRACE = 'TRACE'; /** @@ -60,7 +52,8 @@ class Client * * Your Appwrite project ID. You can find your project ID in your Appwrite console project settings. * - * @param string $value + * @param string $value + * * @return self $this */ public function setProject(string $value): self @@ -75,7 +68,8 @@ class Client * * Your Appwrite project secret key. You can can create a new API key from your Appwrite console API keys dashboard. * - * @param string $value + * @param string $value + * * @return self $this */ public function setKey(string $value): self @@ -88,7 +82,8 @@ class Client /** * Set Locale * - * @param string $value + * @param string $value + * * @return self $this */ public function setLocale(string $value): self @@ -101,7 +96,8 @@ class Client /** * Set Mode * - * @param string $value + * @param string $value + * * @return self $this */ public function setMode(string $value): self @@ -112,7 +108,7 @@ class Client } /** - * @param bool $status true + * @param bool $status true * @return self $this */ public function setSelfSigned(bool $status = true): self @@ -123,7 +119,7 @@ class Client } /** - * @param string $endpoint + * @param string $endpoint * @return self $this */ public function setEndpoint(string $endpoint): self @@ -142,8 +138,9 @@ class Client } /** - * @param string $key - * @param string $value + * @param string $key + * @param string $value + * * @return self $this */ public function addHeader(string $key, string $value): self @@ -158,20 +155,19 @@ class Client * * Make an API call * - * @param string $method - * @param string $path - * @param array $params - * @param array $headers - * @param bool $decode + * @param string $method + * @param string $path + * @param array $params + * @param array $headers + * @param bool $decode * @return array - * * @throws Exception */ public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true): array { - $headers = array_merge($this->headers, $headers); - $ch = curl_init($this->endpoint.$path.(($method == self::METHOD_GET && ! empty($params)) ? '?'.http_build_query($params) : '')); - $responseHeaders = []; + $headers = array_merge($this->headers, $headers); + $ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); + $responseHeaders = []; $query = match ($headers['content-type']) { 'application/json' => json_encode($params), @@ -181,7 +177,7 @@ class Client }; foreach ($headers as $i => $header) { - $headers[] = $i.':'.$header; + $headers[] = $i . ':' . $header; unset($headers[$i]); } @@ -216,15 +212,15 @@ class Client curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - $responseBody = curl_exec($ch); - $responseType = $responseHeaders['content-type'] ?? ''; + $responseBody = curl_exec($ch); + $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($decode && substr($responseType, 0, strpos($responseType, ';')) == 'application/json') { $json = json_decode($responseBody, true); if ($json === null) { - throw new Exception('Failed to parse response: '.$responseBody); + throw new Exception('Failed to parse response: ' . $responseBody); } $responseBody = $json; @@ -232,7 +228,7 @@ class Client } if ((curl_errno($ch))) { - throw new Exception(curl_error($ch).' with status code '.$responseStatus, $responseStatus); + throw new Exception(curl_error($ch) . ' with status code ' . $responseStatus, $responseStatus); } curl_close($ch); @@ -240,19 +236,19 @@ class Client $responseHeaders['status-code'] = $responseStatus; if ($responseStatus === 500) { - echo 'Server error('.$method.': '.$path.'. Params: '.json_encode($params).'): '.json_encode($responseBody)."\n"; + echo 'Server error(' . $method . ': ' . $path . '. Params: ' . json_encode($params) . '): ' . json_encode($responseBody) . "\n"; } return [ 'headers' => $responseHeaders, - 'body' => $responseBody, + 'body' => $responseBody ]; } /** * Parse Cookie String * - * @param string $cookie + * @param string $cookie * @return array */ public function parseCookie(string $cookie): array @@ -267,8 +263,8 @@ class Client /** * Flatten params array to PHP multiple format * - * @param array $data - * @param string $prefix + * @param array $data + * @param string $prefix * @return array */ protected function flatten(array $data, string $prefix = ''): array diff --git a/tests/e2e/General/AbuseTest.php b/tests/e2e/General/AbuseTest.php index ded164af21..f5a2829974 100644 --- a/tests/e2e/General/AbuseTest.php +++ b/tests/e2e/General/AbuseTest.php @@ -34,13 +34,13 @@ class AbuseTest extends Scope $max = 120; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'documentId' => ID::unique(), 'data' => [ - 'title' => 'The Hulk '.$i, + 'title' => 'The Hulk ' . $i, ], ]); @@ -59,7 +59,7 @@ class AbuseTest extends Scope $collectionId = $data['collectionId']; $max = 120; - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -73,12 +73,12 @@ class AbuseTest extends Scope $documentId = $document['body']['$id']; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$documentId, [ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'data' => [ - 'title' => 'The Hulk '.$i, + 'title' => 'The Hulk ' . $i, ], ]); @@ -98,7 +98,7 @@ class AbuseTest extends Scope $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -111,7 +111,7 @@ class AbuseTest extends Scope $documentId = $document['body']['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$documentId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -131,12 +131,12 @@ class AbuseTest extends Scope $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../resources/logo.png'), 'image/png', 'permissions.png'), ]); if ($i < $max) { @@ -153,23 +153,23 @@ class AbuseTest extends Scope $bucketId = $data['bucketId']; $max = 60; - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $response['body']['$id']; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $response = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'name' => 'permissions'.$i.'.png', + 'name' => 'permissions' . $i . '.png', ]); if ($i < $max) { @@ -187,18 +187,18 @@ class AbuseTest extends Scope $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -216,7 +216,7 @@ class AbuseTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'AbuseDatabase', @@ -227,10 +227,10 @@ class AbuseTest extends Scope $databaseId = $database['body']['$id']; - $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', [ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -244,10 +244,10 @@ class AbuseTest extends Scope $collectionId = $movies['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'key' => 'title', 'size' => 256, diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index e3533e31d6..087b984f9d 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -68,7 +68,7 @@ class HTTPTest extends Scope { // Preparation $previousEndpoint = $this->client->getEndpoint(); - $this->client->setEndpoint('http://localhost'); + $this->client->setEndpoint("http://localhost"); /** * Test for SUCCESS @@ -96,7 +96,7 @@ class HTTPTest extends Scope public function testSpecs() { - $directory = __DIR__.'/../../../app/config/specs/'; + $directory = __DIR__ . '/../../../app/config/specs/'; $files = scandir($directory); $client = new Client(); @@ -120,7 +120,7 @@ class HTTPTest extends Scope break; } } - if (! $allowed) { + if (!$allowed) { continue; } @@ -129,7 +129,7 @@ class HTTPTest extends Scope */ $response = $client->call(Client::METHOD_POST, '/validator/debug', [ 'content-type' => 'application/json', - ], json_decode(file_get_contents($directory.$file), true)); + ], json_decode(file_get_contents($directory . $file), true)); $response['body'] = json_decode($response['body'], true); $this->assertEquals(200, $response['headers']['status-code']); diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index d9a662b6ac..c8c4f21165 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -2,12 +2,13 @@ namespace Tests\E2E\General; -use CURLFile; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use CURLFile; use Tests\E2E\Services\Functions\FunctionsBase; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -19,7 +20,6 @@ class UsageTest extends Scope use FunctionsBase; private const WAIT = 35; - private const CREATE = 20; protected string $projectId; @@ -46,21 +46,21 @@ class UsageTest extends Scope $headers['x-appwrite-key'] = $project['apiKey']; $headers['content-type'] = 'application/json'; - $usersTotal = 0; + $usersTotal = 0; $requestsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { - $email = uniqid().'user@usage.test'; + $email = uniqid() . 'user@usage.test'; $password = 'password'; - $name = uniqid().'User'; + $name = uniqid() . 'User'; $res = $this->client->call( Client::METHOD_POST, '/users', $headers, [ - 'userId' => 'unique()', - 'email' => $email, + 'userId' => 'unique()', + 'email' => $email, 'password' => $password, - 'name' => $name, + 'name' => $name, ] ); @@ -71,7 +71,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $userId = $res['body']['$id']; - $res = $this->client->call(Client::METHOD_DELETE, '/users/'.$userId, $headers); + $res = $this->client->call(Client::METHOD_DELETE, '/users/' . $userId, $headers); $this->assertEmpty($res['body']); $requestsTotal++; $usersTotal--; @@ -79,10 +79,10 @@ class UsageTest extends Scope } return [ - 'projectId' => $projectId, - 'headers' => $headers, - 'usersTotal' => $usersTotal, - 'requestsTotal' => $requestsTotal, + 'projectId' => $projectId, + 'headers' => $headers, + 'usersTotal' => $usersTotal, + 'requestsTotal' => $requestsTotal ]; } @@ -93,15 +93,15 @@ class UsageTest extends Scope { sleep(self::WAIT); - $projectId = $data['projectId']; - $headers = $data['headers']; - $usersTotal = $data['usersTotal']; + $projectId = $data['projectId']; + $headers = $data['headers']; + $usersTotal = $data['usersTotal']; $requestsTotal = $data['requestsTotal']; $consoleHeaders = [ 'origin' => 'http://localhost', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => $projectId, 'x-appwrite-mode' => 'admin', ]; @@ -151,8 +151,9 @@ class UsageTest extends Scope $storageTotal = 0; $filesTotal = 0; + for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid().' bucket'; + $name = uniqid() . ' bucket'; $res = $this->client->call( Client::METHOD_POST, '/storage/buckets', @@ -178,7 +179,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/storage/buckets/'.$bucketId, + '/storage/buckets/' . $bucketId, $headers ); $this->assertEmpty($res['body']); @@ -190,19 +191,19 @@ class UsageTest extends Scope // upload some files $files = [ [ - 'path' => realpath(__DIR__.'/../../resources/logo.png'), + 'path' => realpath(__DIR__ . '/../../resources/logo.png'), 'name' => 'logo.png', ], [ - 'path' => realpath(__DIR__.'/../../resources/file.png'), + 'path' => realpath(__DIR__ . '/../../resources/file.png'), 'name' => 'file.png', ], [ - 'path' => realpath(__DIR__.'/../../resources/disk-a/kitten-3.gif'), + 'path' => realpath(__DIR__ . '/../../resources/disk-a/kitten-3.gif'), 'name' => 'kitten-3.gif', ], [ - 'path' => realpath(__DIR__.'/../../resources/disk-a/kitten-1.jpg'), + 'path' => realpath(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'), 'name' => 'kitten-1.jpg', ], ]; @@ -212,7 +213,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_POST, - '/storage/buckets/'.$bucketId.'/files', + '/storage/buckets/' . $bucketId . '/files', array_merge($headers, ['content-type' => 'multipart/form-data']), [ 'fileId' => 'unique()', @@ -231,13 +232,13 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/storage/buckets/'.$bucketId.'/files/'.$fileId, + '/storage/buckets/' . $bucketId . '/files/' . $fileId, $headers ); $this->assertEmpty($res['body']); $requestsTotal++; $filesTotal--; - $storageTotal -= $fileSize; + $storageTotal -= $fileSize; } } @@ -255,11 +256,11 @@ class UsageTest extends Scope */ public function testStorageStats(array $data): array { - $bucketId = $data['bucketId']; - $bucketsTotal = $data['bucketsTotal']; + $bucketId = $data['bucketId']; + $bucketsTotal = $data['bucketsTotal']; $requestsTotal = $data['requestsTotal']; - $storageTotal = $data['storageTotal']; - $filesTotal = $data['filesTotal']; + $storageTotal = $data['storageTotal']; + $filesTotal = $data['filesTotal']; sleep(self::WAIT); @@ -300,7 +301,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_GET, - '/storage/'.$bucketId.'/usage?range=30d', + '/storage/' . $bucketId . '/usage?range=30d', array_merge( $data['headers'], $data['consoleHeaders'] @@ -327,7 +328,7 @@ class UsageTest extends Scope $documentsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid().' database'; + $name = uniqid() . ' database'; $res = $this->client->call( Client::METHOD_POST, '/databases', @@ -338,6 +339,7 @@ class UsageTest extends Scope ] ); + $this->assertEquals($name, $res['body']['name']); $this->assertNotEmpty($res['body']['$id']); $databaseId = $res['body']['$id']; @@ -348,7 +350,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/databases/'.$databaseId, + '/databases/' . $databaseId, $headers ); $this->assertEmpty($res['body']); @@ -359,10 +361,10 @@ class UsageTest extends Scope } for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid().' collection'; + $name = uniqid() . ' collection'; $res = $this->client->call( Client::METHOD_POST, - '/databases/'.$databaseId.'/collections', + '/databases/' . $databaseId . '/collections', $headers, [ 'collectionId' => 'unique()', @@ -387,7 +389,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/databases/'.$databaseId.'/collections/'.$collectionId, + '/databases/' . $databaseId . '/collections/' . $collectionId, $headers ); $this->assertEmpty($res['body']); @@ -398,7 +400,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_POST, - '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes'.'/string', + '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes' . '/string', $headers, [ 'key' => 'name', @@ -413,14 +415,14 @@ class UsageTest extends Scope sleep(self::WAIT); for ($i = 0; $i < self::CREATE; $i++) { - $name = uniqid().' collection'; + $name = uniqid() . ' collection'; $res = $this->client->call( Client::METHOD_POST, - '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', + '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', $headers, [ 'documentId' => 'unique()', - 'data' => ['name' => $name], + 'data' => ['name' => $name] ] ); $this->assertEquals($name, $res['body']['name']); @@ -433,7 +435,7 @@ class UsageTest extends Scope if ($i < (self::CREATE / 2)) { $res = $this->client->call( Client::METHOD_DELETE, - '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$documentId, + '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, $headers ); $this->assertEmpty($res['body']); @@ -453,8 +455,10 @@ class UsageTest extends Scope } /** @depends testPrepareDatabaseStats */ + public function testDatabaseStats(array $data): array { + $projectId = $data['projectId']; $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; @@ -498,7 +502,7 @@ class UsageTest extends Scope $res = $this->client->call( Client::METHOD_GET, - '/databases/'.$databaseId.'/usage?range=30d', + '/databases/' . $databaseId . '/usage?range=30d', $data['consoleHeaders'] ); $res = $res['body']; @@ -509,7 +513,7 @@ class UsageTest extends Scope $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); $this->validateDates($res['documentsTotal']); - $res = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/usage?range=30d', $data['consoleHeaders']); + $res = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', $data['consoleHeaders']); $res = $res['body']; $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); @@ -520,6 +524,7 @@ class UsageTest extends Scope return $data; } + /** @depends testDatabaseStats */ public function testPrepareFunctionsStats(array $data): array { @@ -556,17 +561,17 @@ class UsageTest extends Scope $this->assertEquals(201, $response1['headers']['status-code']); $this->assertNotEmpty($response1['body']['$id']); - $code = realpath(__DIR__.'/../../resources/functions').'/php/code.tar.gz'; + $code = realpath(__DIR__ . '/../../resources/functions') . "/php/code.tar.gz"; $this->packageCode('php'); $deployment = $this->client->call( Client::METHOD_POST, - '/functions/'.$functionId.'/deployments', - array_merge($headers, ['content-type' => 'multipart/form-data']), + '/functions/' . $functionId . '/deployments', + array_merge($headers, ['content-type' => 'multipart/form-data',]), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true, + 'activate' => true ] ); @@ -582,7 +587,7 @@ class UsageTest extends Scope $response = $this->client->call( Client::METHOD_PATCH, - '/functions/'.$functionId.'/deployments/'.$deploymentId, + '/functions/' . $functionId . '/deployments/' . $deploymentId, $headers ); @@ -595,7 +600,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_POST, - '/functions/'.$functionId.'/executions', + '/functions/' . $functionId . '/executions', $headers, [ 'async' => false, @@ -616,7 +621,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_POST, - '/functions/'.$functionId.'/executions', + '/functions/' . $functionId . '/executions', $headers, [ 'async' => false, @@ -635,7 +640,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_POST, - '/functions/'.$functionId.'/executions', + '/functions/' . $functionId . '/executions', $headers, [ 'async' => true, @@ -650,7 +655,7 @@ class UsageTest extends Scope $execution = $this->client->call( Client::METHOD_GET, - '/functions/'.$functionId.'/executions/'.$execution['body']['$id'], + '/functions/' . $functionId . '/executions/' . $execution['body']['$id'], $headers ); @@ -681,7 +686,7 @@ class UsageTest extends Scope $response = $this->client->call( Client::METHOD_GET, - '/functions/'.$functionId.'/usage?range=30d', + '/functions/' . $functionId . '/usage?range=30d', $data['consoleHeaders'] ); diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 7146ebc392..ee41129fde 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -13,19 +13,19 @@ trait ProjectCustom protected static $project = []; /** - * @param bool $fresh + * @param bool $fresh * @return array */ public function getProject(bool $fresh = false): array { - if (! empty(self::$project) && ! $fresh) { + if (!empty(self::$project) && !$fresh) { return self::$project; } $team = $this->client->call(Client::METHOD_POST, '/teams', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'teamId' => ID::unique(), @@ -38,7 +38,7 @@ trait ProjectCustom $project = $this->client->call(Client::METHOD_POST, '/projects', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'projectId' => ID::unique(), @@ -52,10 +52,10 @@ trait ProjectCustom $this->assertEquals(201, $project['headers']['status-code']); $this->assertNotEmpty($project['body']); - $key = $this->client->call(Client::METHOD_POST, '/projects/'.$project['body']['$id'].'/keys', [ + $key = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/keys', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'name' => 'Demo Project Key', @@ -92,10 +92,10 @@ trait ProjectCustom $this->assertNotEmpty($key['body']); $this->assertNotEmpty($key['body']['secret']); - $webhook = $this->client->call(Client::METHOD_POST, '/projects/'.$project['body']['$id'].'/webhooks', [ + $webhook = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/webhooks', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'name' => 'Webhook Test', @@ -104,7 +104,7 @@ trait ProjectCustom // 'functions.*', TODO @christyjacob4 : enable test once we allow functions.* events 'buckets.*', 'teams.*', - 'users.*', + 'users.*' ], 'url' => 'http://request-catcher:5000/webhook', 'security' => false, @@ -130,12 +130,13 @@ trait ProjectCustom public function getNewKey(array $scopes) { + $projectId = self::$project['$id']; - $key = $this->client->call(Client::METHOD_POST, '/projects/'.$projectId.'/keys', [ + $key = $this->client->call(Client::METHOD_POST, '/projects/' . $projectId . '/keys', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'name' => 'Demo Project Key', diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 4eaf846c27..14eb83897b 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Scopes; use Appwrite\Tests\Retryable; -use PHPUnit\Framework\TestCase; use Tests\E2E\Client; +use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; abstract class Scope extends TestCase @@ -12,7 +12,6 @@ abstract class Scope extends TestCase use Retryable; protected ?Client $client = null; - protected string $endpoint = 'http://localhost/v1'; protected function setUp(): void @@ -73,7 +72,7 @@ abstract class Scope extends TestCase return self::$root; } - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -99,7 +98,7 @@ abstract class Scope extends TestCase 'password' => $password, ]); - $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_console']; + $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_console']; self::$root = [ '$id' => ID::custom($root['body']['$id']), @@ -125,7 +124,7 @@ abstract class Scope extends TestCase return self::$user[$this->getProject()['$id']]; } - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -151,7 +150,7 @@ abstract class Scope extends TestCase 'password' => $password, ]); - $token = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $token = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; self::$user[$this->getProject()['$id']] = [ '$id' => ID::custom($user['body']['$id']), diff --git a/tests/e2e/Scopes/SideClient.php b/tests/e2e/Scopes/SideClient.php index 2348da8e6b..54f77a9747 100644 --- a/tests/e2e/Scopes/SideClient.php +++ b/tests/e2e/Scopes/SideClient.php @@ -8,7 +8,7 @@ trait SideClient { return [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$this->getUser()['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $this->getUser()['session'], ]; } diff --git a/tests/e2e/Scopes/SideConsole.php b/tests/e2e/Scopes/SideConsole.php index f067977c14..74a0dd0c60 100644 --- a/tests/e2e/Scopes/SideConsole.php +++ b/tests/e2e/Scopes/SideConsole.php @@ -8,8 +8,8 @@ trait SideConsole { return [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], - 'x-appwrite-mode' => 'admin', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-mode' => 'admin' ]; } diff --git a/tests/e2e/Scopes/SideServer.php b/tests/e2e/Scopes/SideServer.php index f72ac1f2e2..b5e15150e9 100644 --- a/tests/e2e/Scopes/SideServer.php +++ b/tests/e2e/Scopes/SideServer.php @@ -12,7 +12,7 @@ trait SideServer public function getHeaders(): array { return [ - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]; } diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 84c32aede9..291d55b221 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -4,15 +4,15 @@ namespace Tests\E2E\Services\Account; use Appwrite\Tests\Retry; use Tests\E2E\Client; -use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; +use Utopia\Database\DateTime; use Utopia\Database\Validator\Datetime as DatetimeValidator; trait AccountBase { public function testCreateAccount(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -126,13 +126,13 @@ trait AccountBase $this->assertNotFalse(\DateTime::createFromFormat('Y-m-d\TH:i:s.uP', $response['body']['expire'])); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; // apiKey is only available in custom client test $apiKey = $this->getProject()['apiKey']; - if (! empty($apiKey)) { + if (!empty($apiKey)) { $userId = $response['body']['userId']; - $response = $this->client->call(Client::METHOD_GET, '/users/'.$userId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $userId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -163,7 +163,7 @@ trait AccountBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $email.'x', + 'email' => $email . 'x', 'password' => $password, ]); @@ -175,7 +175,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], ]), [ 'email' => $email, - 'password' => $password.'x', + 'password' => $password . 'x', ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -213,7 +213,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -237,7 +237,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_GET, '/account', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session.'xx', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session . 'xx', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -260,7 +260,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -297,7 +297,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -357,7 +357,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -365,7 +365,7 @@ trait AccountBase $this->assertNotEmpty($response['body']['logs']); $this->assertCount(3, $response['body']['logs']); $this->assertIsNumeric($response['body']['total']); - $this->assertContains($response['body']['logs'][1]['event'], ['session.create']); + $this->assertContains($response['body']['logs'][1]['event'], ["session.create"]); $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][1]['time'])); @@ -387,7 +387,7 @@ trait AccountBase $this->assertEquals('--', $response['body']['logs'][1]['countryCode']); $this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']); - $this->assertContains($response['body']['logs'][2]['event'], ['user.create']); + $this->assertContains($response['body']['logs'][2]['event'], ["user.create"]); $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); @@ -413,9 +413,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ], ]); $this->assertEquals($responseLimit['headers']['status-code'], 200); @@ -430,9 +430,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ], ]); $this->assertEquals($responseOffset['headers']['status-code'], 200); @@ -447,9 +447,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'queries' => ['limit(1)', 'offset(1)'], + 'queries' => [ 'limit(1)', 'offset(1)' ], ]); $this->assertEquals($responseLimitOffset['headers']['status-code'], 200); @@ -491,9 +491,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'name' => $newName, + 'name' => $newName ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -519,7 +519,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -528,9 +528,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'name' => 'ocSRq1d3QphHivJyUmYY7WMnrxyjdk5YvVwcDqx2zS0coxESN8RmsQwLWw5Whnf0WbVohuFWTRAaoKgCOO0Y0M7LwgFnZmi8881Y72222222222222222222222222222', + 'name' => 'ocSRq1d3QphHivJyUmYY7WMnrxyjdk5YvVwcDqx2zS0coxESN8RmsQwLWw5Whnf0WbVohuFWTRAaoKgCOO0Y0M7LwgFnZmi8881Y72222222222222222222222222222' ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -557,7 +557,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -595,7 +595,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -607,7 +607,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -621,9 +621,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'password' => 'new-password', + 'password' => 'new-password' ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -637,7 +637,7 @@ trait AccountBase */ public function testUpdateAccountEmail($data): array { - $newEmail = uniqid().'new@localhost.test'; + $newEmail = uniqid() . 'new@localhost.test'; $session = $data['session'] ?? ''; /** @@ -647,7 +647,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $newEmail, 'password' => 'new-password', @@ -675,7 +675,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -691,9 +691,9 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], ]), [ 'userId' => ID::unique(), - 'email' => $data['email'], - 'password' => $data['password'], - 'name' => $data['name'], + 'email' => $data['email'], + 'password' => $data['password'], + 'name' => $data['name'], ]); $this->assertEquals($response['headers']['status-code'], 201); @@ -703,6 +703,7 @@ trait AccountBase $this->assertEquals($response['body']['email'], $data['email']); $this->assertEquals($response['body']['name'], $data['name']); + $data['email'] = $newEmail; return $data; @@ -713,7 +714,7 @@ trait AccountBase */ public function testUpdateAccountPrefs($data): array { - $newEmail = uniqid().'new@localhost.test'; + $newEmail = uniqid() . 'new@localhost.test'; $session = $data['session'] ?? ''; /** @@ -723,12 +724,12 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ], + ] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -752,9 +753,21 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'prefs' => '{}', + 'prefs' => '{}' + ]); + + $this->assertEquals($response['headers']['status-code'], 400); + + + $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]), [ + 'prefs' => '[]' ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -763,20 +776,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'prefs' => '[]', - ]); - - $this->assertEquals($response['headers']['status-code'], 400); - - $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, - ]), [ - 'prefs' => '{"test": "value"}', + 'prefs' => '{"test": "value"}' ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -784,29 +786,29 @@ trait AccountBase /** * Prefs size exceeded */ - $prefsObject = ['longValue' => str_repeat('🍰', 100000)]; + $prefsObject = ["longValue" => str_repeat("🍰", 100000)]; $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'prefs' => $prefsObject, + 'prefs' => $prefsObject ]); $this->assertEquals(400, $response['headers']['status-code']); // Now let's test the same thing, but with normal symbol instead of multi-byte cake emoji - $prefsObject = ['longValue' => str_repeat('-', 100000)]; + $prefsObject = ["longValue" => str_repeat("-", 100000)]; $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'prefs' => $prefsObject, + 'prefs' => $prefsObject ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -830,7 +832,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'url' => 'http://localhost/verification', @@ -848,14 +850,14 @@ trait AccountBase $this->assertEquals('Account Verification', $lastEmail['subject']); $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire='.urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); + $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -866,7 +868,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'url' => 'localhost/verification', ]); @@ -877,7 +879,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'url' => 'http://remotehost/verification', ]); @@ -905,7 +907,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => $verification, @@ -920,7 +922,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => ID::custom('ewewe'), 'secret' => $verification, @@ -932,7 +934,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => 'sdasdasdasd', @@ -965,7 +967,7 @@ trait AccountBase ]); $sessionNewId = $response['body']['$id']; - $sessionNew = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals($response['headers']['status-code'], 201); @@ -973,16 +975,16 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, ]); $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionNewId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -991,7 +993,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -1003,7 +1005,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -1031,14 +1033,14 @@ trait AccountBase 'password' => $password, ]); - $sessionNew = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals($response['headers']['status-code'], 201); $response = $this->client->call(Client::METHOD_GET, '/account', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1047,7 +1049,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1059,7 +1061,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_GET, '/account', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1082,7 +1084,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -1113,7 +1115,7 @@ trait AccountBase 'password' => $password, ]); - $data['session'] = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $data['session'] = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; return $data; } @@ -1151,15 +1153,15 @@ trait AccountBase $recovery = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire='.urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); + $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -1266,7 +1268,7 @@ trait AccountBase ]), [ 'userId' => $id, 'secret' => $recovery, - 'password' => $newPassowrd.'x', + 'password' => $newPassowrd . 'x', 'passwordAgain' => $newPassowrd, ]); @@ -1277,7 +1279,7 @@ trait AccountBase public function testCreateMagicUrl(): array { - $email = \time().'user@appwrite.io'; + $email = \time() . 'user@appwrite.io'; /** * Test for SUCCESS @@ -1305,15 +1307,15 @@ trait AccountBase $token = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire='.urlencode($response['body']['expire']), 0); + $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode($response['body']['expire']), 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -1389,13 +1391,13 @@ trait AccountBase $this->assertNotEmpty($response['body']['userId']); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -1430,6 +1432,7 @@ trait AccountBase $this->assertEquals(401, $response['headers']['status-code']); + $data['sessionId'] = $sessionId; $data['session'] = $session; @@ -1451,9 +1454,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'password' => 'new-password', + 'password' => 'new-password' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -1489,7 +1492,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -1501,7 +1504,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => 'wrong-password', @@ -1515,9 +1518,9 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'password' => 'new-password', + 'password' => 'new-password' ]); $this->assertEquals($response['headers']['status-code'], 401); diff --git a/tests/e2e/Services/Account/AccountConsoleClientTest.php b/tests/e2e/Services/Account/AccountConsoleClientTest.php index c1a248ac49..b517d8c408 100644 --- a/tests/e2e/Services/Account/AccountConsoleClientTest.php +++ b/tests/e2e/Services/Account/AccountConsoleClientTest.php @@ -3,11 +3,11 @@ namespace Tests\E2E\Services\Account; use Appwrite\Extend\Exception; -use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; +use Tests\E2E\Client; use Utopia\Database\Validator\Datetime as DatetimeValidator; class AccountConsoleClientTest extends Scope @@ -18,7 +18,7 @@ class AccountConsoleClientTest extends Scope public function testCreateAccountWithInvite(): void { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -34,7 +34,7 @@ class AccountConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'Invalid Code', + 'code' => 'Invalid Code' ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -66,7 +66,7 @@ class AccountConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'code-zero', + 'code' => 'code-zero' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -76,7 +76,7 @@ class AccountConsoleClientTest extends Scope $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $response = $this->client->call(Client::METHOD_POST, '/account/invite', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', @@ -86,7 +86,7 @@ class AccountConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'code-one', + 'code' => 'code-one' ]); $this->assertEquals(201, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 7ca0798a61..d225496a65 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3,16 +3,18 @@ namespace Tests\E2E\Services\Account; use Appwrite\Extend\Exception; +use Appwrite\SMS\Adapter\Mock; use Appwrite\Tests\Retry; -use function sleep; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; +use function sleep; + class AccountCustomClientTest extends Scope { use AccountBase; @@ -21,7 +23,7 @@ class AccountCustomClientTest extends Scope public function testCreateAccountWithInvite(): void { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -38,7 +40,7 @@ class AccountCustomClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'code' => 'Invalid Code', + 'code' => 'Invalid Code' ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -57,11 +59,11 @@ class AccountCustomClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$this->getProject()['$id'].'/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'provider' => $provider, 'appId' => $appId, @@ -71,7 +73,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/'.$provider, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -86,11 +88,11 @@ class AccountCustomClientTest extends Scope /** * Test for Failure when disabled */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$this->getProject()['$id'].'/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'provider' => $provider, 'appId' => $appId, @@ -100,7 +102,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/'.$provider, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -116,7 +118,7 @@ class AccountCustomClientTest extends Scope public function testBlockedAccount(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name (blocked)'; @@ -150,18 +152,18 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 201); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$id.'/status', [ + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $id . '/status', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -175,7 +177,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 401); @@ -194,9 +196,10 @@ class AccountCustomClientTest extends Scope return []; } + public function testSelfBlockedAccount(): array { - $email = uniqid().'user55@localhost.test'; + $email = uniqid() . 'user55@localhost.test'; $password = 'password'; $name = 'User Name (self blocked)'; @@ -229,13 +232,13 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 201); - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -243,20 +246,20 @@ class AccountCustomClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/account/status', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ], [ 'status' => false, ]); $this->assertEquals($response['headers']['status-code'], 200); - $this->assertStringContainsString('a_session_'.$this->getProject()['$id'].'=deleted', $response['headers']['set-cookie']); + $this->assertStringContainsString('a_session_' . $this->getProject()['$id'] . '=deleted', $response['headers']['set-cookie']); $this->assertEquals('[]', $response['headers']['x-fallback-cookies']); $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 401); @@ -277,7 +280,7 @@ class AccountCustomClientTest extends Scope public function testCreateJWT(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name (JWT)'; @@ -311,13 +314,13 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 201); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -326,7 +329,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 201); @@ -354,11 +357,11 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -391,13 +394,13 @@ class AccountCustomClientTest extends Scope $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; \usleep(1000 * 30); // wait for 30ms to let the shutdown update accessedAt $apiKey = $this->getProject()['apiKey']; $userId = $response['body']['userId']; - $response = $this->client->call(Client::METHOD_GET, '/users/'.$userId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $userId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -414,7 +417,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -434,7 +437,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'oldPassword' => '', ]); @@ -449,7 +452,7 @@ class AccountCustomClientTest extends Scope */ public function testUpdateAnonymousAccountEmail($session) { - $email = uniqid().'new@localhost.test'; + $email = uniqid() . 'new@localhost.test'; /** * Test for FAILURE @@ -458,7 +461,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $email, 'password' => '', @@ -472,7 +475,7 @@ class AccountCustomClientTest extends Scope public function testConvertAnonymousAccount() { $session = $this->testCreateAnonymousAccount(); - $email = uniqid().'new@localhost.test'; + $email = uniqid() . 'new@localhost.test'; $password = 'new-password'; /** @@ -485,14 +488,14 @@ class AccountCustomClientTest extends Scope ]), [ 'userId' => ID::unique(), 'email' => $email, - 'password' => $password, + 'password' => $password ]); $response = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $email, 'password' => $password, @@ -503,13 +506,13 @@ class AccountCustomClientTest extends Scope /** * Test for SUCCESS */ - $email = uniqid().'new@localhost.test'; + $email = uniqid() . 'new@localhost.test'; $response = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $email, 'password' => $password, @@ -537,11 +540,12 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'url' => 'http://localhost', + 'url' => 'http://localhost' ]); + $this->assertEquals($response['headers']['status-code'], 201); return []; @@ -561,18 +565,18 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); $userId = $response['body']['$id'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$this->getProject()['$id'].'/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'provider' => $provider, 'appId' => $appId, @@ -582,17 +586,17 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/'.$provider, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'success' => 'http://localhost/v1/mock/tests/general/oauth2/success', 'failure' => 'http://localhost/v1/mock/tests/general/oauth2/failure', ]); - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('success', $response['body']['result']); @@ -601,7 +605,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -617,7 +621,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals(200, $response['headers']['status-code']); @@ -633,7 +637,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals(200, $response['headers']['status-code']); @@ -652,7 +656,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -660,11 +664,11 @@ class AccountCustomClientTest extends Scope $sessionID = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/'.$sessionID, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/' . $sessionID, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -674,7 +678,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 404); @@ -737,7 +741,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'search' => '"'.$email.'"', + 'search' => '"' . $email . '"', ]); @@ -762,6 +766,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['body']['users'][0]['email'], $email); } + public function testCreatePhone(): array { $number = '+123456789'; @@ -793,7 +798,7 @@ class AccountCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'userId' => ID::unique(), + 'userId' => ID::unique() ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -869,13 +874,13 @@ class AccountCustomClientTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['userId']); - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -910,19 +915,19 @@ class AccountCustomClientTest extends Scope public function testConvertPhoneToPassword(array $data): array { $session = $data['session']; - $email = uniqid().'new@localhost.test'; + $email = uniqid() . 'new@localhost.test'; $password = 'new-password'; /** * Test for SUCCESS */ - $email = uniqid().'new@localhost.test'; + $email = uniqid() . 'new@localhost.test'; $response = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $email, 'password' => $password, @@ -964,10 +969,10 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'phone' => $newPhone, - 'password' => 'new-password', + 'password' => 'new-password' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -992,7 +997,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), []); $this->assertEquals($response['headers']['status-code'], 400); @@ -1017,7 +1022,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); @@ -1031,7 +1036,7 @@ class AccountCustomClientTest extends Scope $smsRequest = $this->getLastRequest(); return \array_merge($data, [ - 'token' => $smsRequest['data']['message'], + 'token' => $smsRequest['data']['message'] ]); } @@ -1051,7 +1056,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => $secret, @@ -1066,7 +1071,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => ID::custom('ewewe'), 'secret' => $secret, @@ -1078,7 +1083,7 @@ class AccountCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => '999999', diff --git a/tests/e2e/Services/Account/AccountCustomServerTest.php b/tests/e2e/Services/Account/AccountCustomServerTest.php index 6c6c2df654..143277608d 100644 --- a/tests/e2e/Services/Account/AccountCustomServerTest.php +++ b/tests/e2e/Services/Account/AccountCustomServerTest.php @@ -15,7 +15,7 @@ class AccountCustomServerTest extends Scope public function testCreateAccount(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; diff --git a/tests/e2e/Services/Avatars/AvatarsBase.php b/tests/e2e/Services/Avatars/AvatarsBase.php index a7518d38af..e2ddc1a863 100644 --- a/tests/e2e/Services/Avatars/AvatarsBase.php +++ b/tests/e2e/Services/Avatars/AvatarsBase.php @@ -45,6 +45,7 @@ trait AvatarsBase /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_GET, '/avatars/credit-cards/unknown', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -107,6 +108,7 @@ trait AvatarsBase /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_GET, '/avatars/browsers/unknown', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -260,7 +262,7 @@ trait AvatarsBase $response = $this->client->call(Client::METHOD_GET, '/avatars/image', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'url' => 'invalid://appwrite.io/images/apple.png', + 'url' => 'invalid://appwrite.io/images/apple.png' ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -347,7 +349,7 @@ trait AvatarsBase $this->assertEquals(400, $image->getImageWidth()); $this->assertEquals(400, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-default.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-default.png')), strlen($response['body'])); $response = $this->client->call(Client::METHOD_GET, '/avatars/qr', [ 'x-appwrite-project' => $this->getProject()['$id'], @@ -365,7 +367,7 @@ trait AvatarsBase $this->assertEquals(200, $image->getImageWidth()); $this->assertEquals(200, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-size-200.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-size-200.png')), strlen($response['body'])); $response = $this->client->call(Client::METHOD_GET, '/avatars/qr', [ 'x-appwrite-project' => $this->getProject()['$id'], @@ -384,7 +386,7 @@ trait AvatarsBase $this->assertEquals(200, $image->getImageWidth()); $this->assertEquals(200, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); $response = $this->client->call(Client::METHOD_GET, '/avatars/qr', [ 'x-appwrite-project' => $this->getProject()['$id'], @@ -400,7 +402,7 @@ trait AvatarsBase $this->assertEquals(200, $image->getImageWidth()); $this->assertEquals(200, $image->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/qr/qr-size-200-margin-10.png')), strlen($response['body'])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('attachment; filename="qr.png"', $response['headers']['content-disposition']); @@ -446,6 +448,7 @@ trait AvatarsBase return []; } + public function testGetInitials() { /** @@ -526,11 +529,11 @@ trait AvatarsBase $image = new \Imagick(); $image->readImageBlob($response['body']); - $original = new \Imagick(__DIR__.'/../../../resources/initials.png'); + $original = new \Imagick(__DIR__ . '/../../../resources/initials.png'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $this->assertEquals(strlen(\file_get_contents(__DIR__.'/../../../resources/initials.png')), strlen($response['body'])); + $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/initials.png')), strlen($response['body'])); } } diff --git a/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php b/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php index bfd17ef1e9..a59d694114 100644 --- a/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php +++ b/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Avatars; -use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; class AvatarsConsoleClientTest extends Scope diff --git a/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php b/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php index edf09d5ba1..dc399971a0 100644 --- a/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php +++ b/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Avatars; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; class AvatarsCustomClientTest extends Scope diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 9bc081d2ab..c2c1c70bd6 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -5,11 +5,12 @@ namespace Tests\E2E\Services\Databases; use Appwrite\Extend\Exception; use Tests\E2E\Client; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; trait DatabasesBase @@ -22,10 +23,10 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'databaseId' => ID::unique(), - 'name' => 'Test Database', + 'name' => 'Test Database' ]); $this->assertNotEmpty($database['body']['$id']); @@ -44,10 +45,10 @@ trait DatabasesBase /** * Test for SUCCESS */ - $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -60,10 +61,10 @@ trait DatabasesBase $this->assertEquals(201, $movies['headers']['status-code']); $this->assertEquals($movies['body']['name'], 'Movies'); - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -92,10 +93,10 @@ trait DatabasesBase /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Movies', 'enabled' => false, @@ -106,7 +107,7 @@ trait DatabasesBase $this->assertFalse($response['body']['enabled']); if ($this->getSide() === 'client') { - $responseCreateDocument = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $responseCreateDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -123,14 +124,14 @@ trait DatabasesBase $this->assertEquals(404, $responseCreateDocument['headers']['status-code']); - $responseListDocument = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $responseListDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $responseListDocument['headers']['status-code']); - $responseGetDocument = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/someID', array_merge([ + $responseGetDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/someID', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -138,10 +139,10 @@ trait DatabasesBase $this->assertEquals(404, $responseGetDocument['headers']['status-code']); } - $response = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Movies', 'enabled' => true, @@ -159,20 +160,20 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - $title = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ + $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $description = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ + $description = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'description', 'size' => 512, @@ -180,10 +181,10 @@ trait DatabasesBase 'default' => '', ]); - $tagline = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ + $tagline = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'tagline', 'size' => 512, @@ -191,10 +192,10 @@ trait DatabasesBase 'default' => '', ]); - $releaseYear = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/integer', array_merge([ + $releaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'releaseYear', 'required' => true, @@ -202,20 +203,20 @@ trait DatabasesBase 'max' => 2200, ]); - $duration = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/integer', array_merge([ + $duration = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'duration', 'required' => false, 'min' => 60, ]); - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/string', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'actors', 'size' => 256, @@ -223,25 +224,25 @@ trait DatabasesBase 'array' => true, ]); - $datetime = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/datetime', array_merge([ + $datetime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'birthDay', 'required' => false, ]); - $relationship = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes/relationship', array_merge([ + $relationship = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'starringActors', - 'twoWayKey' => 'movie', + 'twoWayKey' => 'movie' ]); $this->assertEquals(202, $title['headers']['status-code']); @@ -297,10 +298,10 @@ trait DatabasesBase // wait for database worker to create attributes sleep(2); - $movies = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ + $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertIsArray($movies['body']['attributes']); @@ -323,7 +324,7 @@ trait DatabasesBase public function testListAttributes(array $data): void { $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -332,7 +333,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, \count($response['body']['attributes'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/attributes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -349,10 +350,10 @@ trait DatabasesBase public function testAttributeResponseModels(array $data): array { $databaseId = $data['databaseId']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Response Models', @@ -365,12 +366,12 @@ trait DatabasesBase $collectionId = $collection['body']['$id']; - $attributesPath = '/databases/'.$databaseId."/collections/{$collectionId}/attributes"; + $attributesPath = "/databases/" . $databaseId . "/collections/{$collectionId}/attributes"; - $string = $this->client->call(Client::METHOD_POST, $attributesPath.'/string', array_merge([ + $string = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'string', 'size' => 16, @@ -378,20 +379,20 @@ trait DatabasesBase 'default' => 'default', ]); - $email = $this->client->call(Client::METHOD_POST, $attributesPath.'/email', array_merge([ + $email = $this->client->call(Client::METHOD_POST, $attributesPath . '/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'email', 'required' => false, 'default' => 'default@example.com', ]); - $enum = $this->client->call(Client::METHOD_POST, $attributesPath.'/enum', array_merge([ + $enum = $this->client->call(Client::METHOD_POST, $attributesPath . '/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'enum', 'elements' => ['yes', 'no', 'maybe'], @@ -399,80 +400,80 @@ trait DatabasesBase 'default' => 'maybe', ]); - $ip = $this->client->call(Client::METHOD_POST, $attributesPath.'/ip', array_merge([ + $ip = $this->client->call(Client::METHOD_POST, $attributesPath . '/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'ip', 'required' => false, 'default' => '192.0.2.0', ]); - $url = $this->client->call(Client::METHOD_POST, $attributesPath.'/url', array_merge([ + $url = $this->client->call(Client::METHOD_POST, $attributesPath . '/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'url', 'required' => false, 'default' => 'http://example.com', ]); - $integer = $this->client->call(Client::METHOD_POST, $attributesPath.'/integer', array_merge([ + $integer = $this->client->call(Client::METHOD_POST, $attributesPath . '/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'integer', 'required' => false, 'min' => 1, 'max' => 5, - 'default' => 3, + 'default' => 3 ]); - $float = $this->client->call(Client::METHOD_POST, $attributesPath.'/float', array_merge([ + $float = $this->client->call(Client::METHOD_POST, $attributesPath . '/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'float', 'required' => false, 'min' => 1.5, 'max' => 5.5, - 'default' => 3.5, + 'default' => 3.5 ]); - $boolean = $this->client->call(Client::METHOD_POST, $attributesPath.'/boolean', array_merge([ + $boolean = $this->client->call(Client::METHOD_POST, $attributesPath . '/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'boolean', 'required' => false, 'default' => true, ]); - $datetime = $this->client->call(Client::METHOD_POST, $attributesPath.'/datetime', array_merge([ + $datetime = $this->client->call(Client::METHOD_POST, $attributesPath . '/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'datetime', 'required' => false, 'default' => null, ]); - $relationship = $this->client->call(Client::METHOD_POST, $attributesPath.'/relationship', array_merge([ + $relationship = $this->client->call(Client::METHOD_POST, $attributesPath . '/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'relationship', - 'twoWayKey' => 'twoWayKey', + 'twoWayKey' => 'twoWayKey' ]); $this->assertEquals(202, $string['headers']['status-code']); @@ -562,64 +563,64 @@ trait DatabasesBase // Wait for database worker to create attributes sleep(5); - $stringResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$string['body']['key'], array_merge([ + $stringResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $string['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $emailResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$email['body']['key'], array_merge([ + $emailResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $email['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $enumResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$enum['body']['key'], array_merge([ + $enumResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $enum['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $ipResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$ip['body']['key'], array_merge([ + $ipResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $ip['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $urlResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$url['body']['key'], array_merge([ + $urlResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $url['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $integerResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$integer['body']['key'], array_merge([ + $integerResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $integer['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $floatResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$float['body']['key'], array_merge([ + $floatResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $float['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $booleanResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$boolean['body']['key'], array_merge([ + $booleanResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $boolean['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $datetimeResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$datetime['body']['key'], array_merge([ + $datetimeResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $datetime['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $relationshipResponse = $this->client->call(Client::METHOD_GET, $attributesPath.'/'.$relationship['body']['key'], array_merge([ + $relationshipResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $relationship['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $stringResponse['headers']['status-code']); @@ -715,10 +716,10 @@ trait DatabasesBase $this->assertEquals($relationship['body']['twoWay'], $relationshipResponse['body']['twoWay']); $this->assertEquals($relationship['body']['twoWayKey'], $relationshipResponse['body']['twoWayKey']); - $attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes', array_merge([ + $attributes = $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'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $attributes['headers']['status-code']); @@ -811,10 +812,10 @@ trait DatabasesBase $this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']); $this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -910,10 +911,10 @@ trait DatabasesBase /** * Test for FAILURE */ - $badEnum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ + $badEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'enum', 'elements' => ['yes', 'no', ''], @@ -934,10 +935,10 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - $titleIndex = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $titleIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'titleIndex', 'type' => 'fulltext', @@ -950,10 +951,10 @@ trait DatabasesBase $this->assertCount(1, $titleIndex['body']['attributes']); $this->assertEquals('title', $titleIndex['body']['attributes'][0]); - $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'releaseYear', 'type' => 'key', @@ -966,10 +967,10 @@ trait DatabasesBase $this->assertCount(1, $releaseYearIndex['body']['attributes']); $this->assertEquals('releaseYear', $releaseYearIndex['body']['attributes'][0]); - $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'releaseYearDated', 'type' => 'key', @@ -987,10 +988,10 @@ trait DatabasesBase // wait for database worker to create index sleep(2); - $movies = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'], array_merge([ + $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $this->assertIsArray($movies['body']['indexes']); @@ -1002,10 +1003,10 @@ trait DatabasesBase $this->assertEquals('available', $movies['body']['indexes'][1]['status']); $this->assertEquals('available', $movies['body']['indexes'][2]['status']); - $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $releaseWithDate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'birthDay', 'type' => 'key', @@ -1019,10 +1020,10 @@ trait DatabasesBase $this->assertEquals('birthDay', $releaseWithDate['body']['attributes'][0]); // Test for failure - $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'releaseYearDated', 'type' => 'fulltext', @@ -1032,10 +1033,10 @@ trait DatabasesBase $this->assertEquals(400, $fulltextReleaseYear['headers']['status-code']); $this->assertEquals($fulltextReleaseYear['body']['message'], 'Attribute "releaseYear" cannot be part of a FULLTEXT index, must be of type string'); - $noAttributes = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $noAttributes = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'none', 'type' => 'key', @@ -1045,10 +1046,10 @@ trait DatabasesBase $this->assertEquals(400, $noAttributes['headers']['status-code']); $this->assertEquals($noAttributes['body']['message'], 'No attributes provided for index'); - $duplicates = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $duplicates = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'duplicate', 'type' => 'fulltext', @@ -1058,7 +1059,7 @@ trait DatabasesBase $this->assertEquals(400, $duplicates['headers']['status-code']); $this->assertEquals($duplicates['body']['message'], 'Duplicate attributes provided'); - $tooLong = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $tooLong = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1080,7 +1081,7 @@ trait DatabasesBase public function testListIndexes(array $data): void { $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1089,7 +1090,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, \count($response['body']['indexes'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1106,7 +1107,7 @@ trait DatabasesBase public function testCreateDocument(array $data): array { $databaseId = $data['databaseId']; - $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1118,16 +1119,16 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ], + ] ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1140,16 +1141,16 @@ trait DatabasesBase 'Tom Holland', 'Zendaya Maree Stoermer', 'Samuel Jackson', - ], + ] ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); - $document3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1168,10 +1169,10 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); - $document4 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1183,7 +1184,7 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals(201, $document1['headers']['status-code']); @@ -1231,7 +1232,7 @@ trait DatabasesBase $this->assertEquals(400, $document4['headers']['status-code']); // Delete document 4 with incomplete path - $this->assertEquals(404, $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/', array_merge([ + $this->assertEquals(404, $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()))['headers']['status-code']); @@ -1245,7 +1246,7 @@ trait DatabasesBase public function testListDocuments(array $data): array { $databaseId = $data['databaseId']; - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1267,7 +1268,7 @@ trait DatabasesBase $this->assertEquals($databaseId, $document['$databaseId']); } - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1289,10 +1290,10 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'databaseId' => ID::custom('default'), - 'name' => 'Default', + 'name' => 'Default' ]); $this->assertNotEmpty($database['body']['$id']); @@ -1301,10 +1302,11 @@ trait DatabasesBase /** * Test for SUCCESS */ + $movies = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -1326,7 +1328,8 @@ trait DatabasesBase /** * Test for SUCCESS */ - $documents = $this->client->call(Client::METHOD_GET, '/database/collections/'.$data['moviesId'].'/documents', array_merge([ + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1344,7 +1347,7 @@ trait DatabasesBase { $databaseId = $data['databaseId']; foreach ($data['documents'] as $document) { - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$document['$collectionId'].'/documents/'.$document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1370,7 +1373,7 @@ trait DatabasesBase $databaseId = $data['databaseId']; $document = $data['documents'][0]; - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$document['$collectionId'].'/documents/'.$document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1394,7 +1397,7 @@ trait DatabasesBase /** * Test after without order. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1405,11 +1408,11 @@ trait DatabasesBase $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['documents'][0]['$id'].'")'], + 'queries' => ['cursorAfter("' . $base['body']['documents'][0]['$id'] . '")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1417,11 +1420,11 @@ trait DatabasesBase $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][1]['$id']); $this->assertCount(2, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['documents'][2]['$id'].'")'], + 'queries' => ['cursorAfter("' . $base['body']['documents'][2]['$id'] . '")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1430,7 +1433,7 @@ trait DatabasesBase /** * Test with ASC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1443,11 +1446,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['documents'][1]['$id'].'")', 'orderAsc("releaseYear")'], + 'queries' => ['cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1457,7 +1460,7 @@ trait DatabasesBase /** * Test with DESC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1470,11 +1473,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['documents'][1]['$id'].'")', 'orderDesc("releaseYear")'], + 'queries' => ['cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1484,7 +1487,7 @@ trait DatabasesBase /** * Test after with unknown document. */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1505,7 +1508,7 @@ trait DatabasesBase /** * Test before without order. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1516,11 +1519,11 @@ trait DatabasesBase $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['documents'][2]['$id'].'")'], + 'queries' => ['cursorBefore("' . $base['body']['documents'][2]['$id'] . '")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1528,11 +1531,11 @@ trait DatabasesBase $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][1]['$id']); $this->assertCount(2, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['documents'][0]['$id'].'")'], + 'queries' => ['cursorBefore("' . $base['body']['documents'][0]['$id'] . '")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1541,7 +1544,7 @@ trait DatabasesBase /** * Test with ASC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1554,11 +1557,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['documents'][1]['$id'].'")', 'orderAsc("releaseYear")'], + 'queries' => ['cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1568,7 +1571,7 @@ trait DatabasesBase /** * Test with DESC order and after. */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1581,11 +1584,11 @@ trait DatabasesBase $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); $this->assertCount(3, $base['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['documents'][1]['$id'].'")', 'orderDesc("releaseYear")'], + 'queries' => ['cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1601,7 +1604,7 @@ trait DatabasesBase public function testListDocumentsLimitAndOffset(array $data): array { $databaseId = $data['databaseId']; - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1612,7 +1615,7 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1633,7 +1636,7 @@ trait DatabasesBase public function testDocumentsListQueries(array $data): array { $databaseId = $data['databaseId']; - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1644,18 +1647,18 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("$id", "'.$documents['body']['documents'][0]['$id'].'")'], + 'queries' => ['equal("$id", "' . $documents['body']['documents'][0]['$id'] . '")'], ]); $this->assertEquals(200, $documents['headers']['status-code']); $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1666,7 +1669,7 @@ trait DatabasesBase $this->assertEquals(2017, $documents['body']['documents'][0]['releaseYear']); $this->assertCount(1, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1678,7 +1681,7 @@ trait DatabasesBase $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); $this->assertCount(2, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1688,7 +1691,7 @@ trait DatabasesBase $this->assertCount(1, $documents['body']['documents']); $this->assertEquals('Captain America', $documents['body']['documents'][0]['title']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1699,7 +1702,7 @@ trait DatabasesBase $this->assertEquals('Spider-Man: Far From Home', $documents['body']['documents'][0]['title']); $this->assertEquals('Spider-Man: Homecoming', $documents['body']['documents'][1]['title']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1708,7 +1711,7 @@ trait DatabasesBase $this->assertCount(3, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1717,7 +1720,7 @@ trait DatabasesBase $this->assertCount(0, $documents['body']['documents']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1725,7 +1728,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1746,11 +1749,11 @@ trait DatabasesBase $conditions[] = $i; } - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("releaseYear", ['.implode(',', $conditions).'])'], + 'queries' => ['equal("releaseYear", [' . implode(',', $conditions) . '])'], ]); $this->assertEquals(400, $documents['headers']['status-code']); @@ -1758,19 +1761,19 @@ trait DatabasesBase $conditions = []; for ($i = 0; $i < 101; $i++) { - $conditions[] = '['.$i.'] Too long title to cross 2k chars query limit'; + $conditions[] = "[" . $i . "] Too long title to cross 2k chars query limit"; } - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['search("title", '.implode(',', $conditions).')'], + 'queries' => ['search("title", ' . implode(',', $conditions) . ')'], ]); $this->assertEquals(400, $documents['headers']['status-code']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1788,7 +1791,7 @@ trait DatabasesBase public function testUpdateDocument(array $data): array { $databaseId = $data['databaseId']; - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1798,7 +1801,7 @@ trait DatabasesBase 'releaseYear' => 2017, 'birthDay' => '1976-06-12 14:12:55', 'actors' => [], - '$createdAt' => 5, // Should be ignored + '$createdAt' => 5 // Should be ignored ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), @@ -1822,7 +1825,7 @@ trait DatabasesBase $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1847,7 +1850,7 @@ trait DatabasesBase $this->assertContains(Permission::update(Role::users()), $document['body']['$permissions']); $this->assertContains(Permission::delete(Role::users()), $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1861,7 +1864,7 @@ trait DatabasesBase $this->assertEquals($document['body']['title'], 'Thor: Ragnarok'); $this->assertEquals($document['body']['releaseYear'], 2017); - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-timestamp' => DateTime::formatTz(DateTime::now()), @@ -1876,7 +1879,8 @@ trait DatabasesBase /** * Test for failure */ - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-timestamp' => 'invalid', @@ -1890,7 +1894,7 @@ trait DatabasesBase $this->assertEquals('Invalid X-Appwrite-Timestamp header value', $response['body']['message']); $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-timestamp' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -1000)), @@ -1913,7 +1917,7 @@ trait DatabasesBase public function testDeleteDocument(array $data): array { $databaseId = $data['databaseId']; - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1928,28 +1932,28 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); $id = $document['body']['$id']; $this->assertEquals(201, $document['headers']['status-code']); - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $document['headers']['status-code']); - $document = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $document['headers']['status-code']); - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1964,7 +1968,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'InvalidDocumentDatabase', @@ -1973,10 +1977,10 @@ trait DatabasesBase $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'invalidDocumentStructure', @@ -1992,48 +1996,48 @@ trait DatabasesBase $collectionId = $collection['body']['$id']; - $email = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email', array_merge([ + $email = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'email', 'required' => false, ]); - $enum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ + $enum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'enum', 'elements' => ['yes', 'no', 'maybe'], 'required' => false, ]); - $ip = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip', array_merge([ + $ip = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'ip', 'required' => false, ]); - $url = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url', array_merge([ + $url = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'url', 'size' => 256, 'required' => false, ]); - $range = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + $range = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'range', 'required' => false, @@ -2042,10 +2046,10 @@ trait DatabasesBase ]); // TODO@kodumbeats min and max are rounded in error message - $floatRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float', array_merge([ + $floatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'floatRange', 'required' => false, @@ -2053,10 +2057,10 @@ trait DatabasesBase 'max' => 1.4, ]); - $probability = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float', array_merge([ + $probability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'probability', 'required' => false, @@ -2065,20 +2069,20 @@ trait DatabasesBase 'max' => 1, ]); - $upperBound = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + $upperBound = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'upperBound', 'required' => false, 'max' => 10, ]); - $lowerBound = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + $lowerBound = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'lowerBound', 'required' => false, @@ -2088,9 +2092,10 @@ trait DatabasesBase /** * Test for failure */ - $invalidRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + + $invalidRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'invalidRange', 'required' => false, @@ -2098,9 +2103,9 @@ trait DatabasesBase 'max' => 3, ]); - $defaultArray = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + $defaultArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'defaultArray', 'required' => false, @@ -2108,54 +2113,54 @@ trait DatabasesBase 'array' => true, ]); - $defaultRequired = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + $defaultRequired = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'attributeId' => ID::custom('defaultRequired'), 'required' => true, - 'default' => 12, + 'default' => 12 ]); - $enumDefault = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ + $enumDefault = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'attributeId' => ID::custom('enumDefault'), 'elements' => ['north', 'west'], - 'default' => 'south', + 'default' => 'south' ]); - $enumDefaultStrict = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ + $enumDefaultStrict = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'attributeId' => ID::custom('enumDefault'), 'elements' => ['north', 'west'], - 'default' => 'NORTH', + 'default' => 'NORTH' ]); - $goodDatetime = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime', array_merge([ + $goodDatetime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'birthDay', 'required' => false, - 'default' => null, + 'default' => null ]); - $datetimeDefault = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime', array_merge([ + $datetimeDefault = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'badBirthDay', 'required' => false, - 'default' => 'bad', + 'default' => 'bad' ]); $this->assertEquals(202, $email['headers']['status-code']); @@ -2179,7 +2184,7 @@ trait DatabasesBase // wait for worker to add attributes sleep(3); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -2190,7 +2195,8 @@ trait DatabasesBase /** * Test for successful validation */ - $goodEmail = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + + $goodEmail = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2202,10 +2208,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $goodEnum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $goodEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2217,10 +2223,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $goodIp = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $goodIp = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2232,10 +2238,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $goodUrl = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $goodUrl = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2247,10 +2253,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $goodRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $goodRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2262,10 +2268,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $goodFloatRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $goodFloatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2277,10 +2283,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $goodProbability = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $goodProbability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2292,10 +2298,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $notTooHigh = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $notTooHigh = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2307,10 +2313,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $notTooLow = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $notTooLow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2322,7 +2328,7 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); $this->assertEquals(201, $goodEmail['headers']['status-code']); @@ -2339,7 +2345,7 @@ trait DatabasesBase * Test that custom validators reject documents */ - $badEmail = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badEmail = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2351,10 +2357,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badEnum = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2366,10 +2372,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badIp = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badIp = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2381,10 +2387,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badUrl = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badUrl = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2396,10 +2402,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2411,10 +2417,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badFloatRange = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badFloatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2426,10 +2432,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badProbability = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badProbability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2441,10 +2447,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $tooHigh = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $tooHigh = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2456,10 +2462,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $tooLow = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $tooLow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2471,10 +2477,10 @@ trait DatabasesBase Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); - $badTime = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $badTime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2482,8 +2488,8 @@ trait DatabasesBase 'data' => [ 'birthDay' => '2020-10-10 27:30:10+01:00', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(400, $badEmail['headers']['status-code']); @@ -2513,7 +2519,7 @@ trait DatabasesBase public function testDefaultPermissions(array $data): array { $databaseId = $data['databaseId']; - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2546,7 +2552,7 @@ trait DatabasesBase // Updated Permissions - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2557,7 +2563,7 @@ trait DatabasesBase ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), - Permission::update(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])) ], ]); @@ -2574,7 +2580,7 @@ trait DatabasesBase Permission::update(Role::user($this->getUser()['$id'])), ], $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2591,7 +2597,7 @@ trait DatabasesBase // Reset Permissions - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2610,7 +2616,7 @@ trait DatabasesBase $this->assertEquals([], $document['body']['$permissions']); // Check client side can no longer read the document. - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2632,7 +2638,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'EnforceCollectionAndDocumentPermissions', @@ -2642,10 +2648,10 @@ trait DatabasesBase $databaseId = $database['body']['$id']; $user = $this->getUser()['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'enforceCollectionAndDocumentPermissions', @@ -2666,10 +2672,10 @@ trait DatabasesBase sleep(2); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'attribute', 'size' => 64, @@ -2682,10 +2688,10 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'key_attribute', 'type' => 'key', @@ -2698,7 +2704,7 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2710,12 +2716,12 @@ trait DatabasesBase Permission::read(Role::user($user)), Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ], + ] ]); $this->assertEquals(201, $document1['headers']['status-code']); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2726,15 +2732,15 @@ trait DatabasesBase 'permissions' => [ Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ], + ] ]); $this->assertEquals(201, $document2['headers']['status-code']); - $document3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'documentId' => ID::unique(), 'data' => [ @@ -2748,7 +2754,7 @@ trait DatabasesBase $this->assertEquals(201, $document3['headers']['status-code']); - $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2757,7 +2763,7 @@ trait DatabasesBase $this->assertEquals(3, $documentsUser1['body']['total']); $this->assertCount(3, $documentsUser1['body']['documents']); - $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], array_merge([ + $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2765,7 +2771,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(200, $document3GetWithCollectionRead['headers']['status-code']); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; $this->client->call(Client::METHOD_POST, '/account', [ @@ -2786,33 +2792,33 @@ trait DatabasesBase 'email' => $email, 'password' => $password, ]); - $session2 = $this->client->parseCookie((string) $session2['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session2 = $this->client->parseCookie((string)$session2['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; - $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], [ + $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); // Current user has no collection permissions but has read permission for this document $this->assertEquals(200, $document3GetWithDocumentRead['headers']['status-code']); - $document2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document2['body']['$id'], [ + $document2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document2['body']['$id'], [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); // Current user has no collection or document permissions for this document $this->assertEquals(404, $document2GetFailure['headers']['status-code']); - $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); // Current user has no collection permissions but has read permission for one document @@ -2825,7 +2831,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'EnforceCollectionPermissions', @@ -2835,10 +2841,10 @@ trait DatabasesBase $databaseId = $database['body']['$id']; $user = $this->getUser()['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'enforceCollectionPermissions', @@ -2858,10 +2864,10 @@ trait DatabasesBase sleep(2); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'attribute', 'size' => 64, @@ -2874,10 +2880,10 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'key_attribute', 'type' => 'key', @@ -2890,7 +2896,7 @@ trait DatabasesBase // wait for db to add attribute sleep(2); - $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2902,12 +2908,12 @@ trait DatabasesBase Permission::read(Role::user($user)), Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ], + ] ]); $this->assertEquals(201, $document1['headers']['status-code']); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2918,15 +2924,15 @@ trait DatabasesBase 'permissions' => [ Permission::update(Role::user($user)), Permission::delete(Role::user($user)), - ], + ] ]); $this->assertEquals(201, $document2['headers']['status-code']); - $document3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'documentId' => ID::unique(), 'data' => [ @@ -2940,7 +2946,7 @@ trait DatabasesBase $this->assertEquals(201, $document3['headers']['status-code']); - $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2949,7 +2955,7 @@ trait DatabasesBase $this->assertEquals(3, $documentsUser1['body']['total']); $this->assertCount(3, $documentsUser1['body']['documents']); - $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], array_merge([ + $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2957,7 +2963,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(200, $document3GetWithCollectionRead['headers']['status-code']); - $email = uniqid().'user2@localhost.test'; + $email = uniqid() . 'user2@localhost.test'; $password = 'password'; $name = 'User Name'; $this->client->call(Client::METHOD_POST, '/account', [ @@ -2978,43 +2984,43 @@ trait DatabasesBase 'email' => $email, 'password' => $password, ]); - $session2 = $this->client->parseCookie((string) $session2['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session2 = $this->client->parseCookie((string)$session2['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; - $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents/'.$document3['body']['$id'], [ + $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); // Current user has no collection permissions and document permissions are disabled $this->assertEquals(404, $document3GetWithDocumentRead['headers']['status-code']); - $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); // Current user has no collection permissions and document permissions are disabled $this->assertEquals(404, $documentsUser2['headers']['status-code']); // Enable document permissions - $collection = $this->client->call(CLient::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$collectionId, [ + $collection = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'name' => $collection['body']['name'], 'documentSecurity' => true, ]); - $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', [ + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session2, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); // Current user has no collection permissions read access to one document @@ -3028,10 +3034,10 @@ trait DatabasesBase public function testUniqueIndexDuplicate(array $data): array { $databaseId = $data['databaseId']; - $uniqueIndex = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/indexes', array_merge([ + $uniqueIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'unique_title', 'type' => 'unique', @@ -3043,7 +3049,7 @@ trait DatabasesBase sleep(2); // test for failure - $duplicate = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $duplicate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3054,19 +3060,19 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ], + ] ], 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); $this->assertEquals(409, $duplicate['headers']['status-code']); // Test for exception when updating document to conflict - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3077,19 +3083,19 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ], + ] ], 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); $this->assertEquals(201, $document['headers']['status-code']); // Test for exception when updating document to conflict - $duplicate = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/documents/'.$document['body']['$id'], array_merge([ + $duplicate = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3100,13 +3106,13 @@ trait DatabasesBase 'actors' => [ 'Chris Evans', 'Samuel Jackson', - ], + ] ], 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); $this->assertEquals(409, $duplicate['headers']['status-code']); @@ -3125,15 +3131,15 @@ trait DatabasesBase ], $this->getHeaders()) : [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]; - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$data['databaseId'].'/collections/'.$data['moviesId'].'/documents', $headers, [ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents', $headers, [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Creation Date Test', - 'releaseYear' => 2000, - ], + 'releaseYear' => 2000 + ] ]); $this->assertEquals($document['body']['title'], 'Creation Date Test'); @@ -3144,10 +3150,10 @@ trait DatabasesBase \sleep(1); - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$data['databaseId'].'/collections/'.$data['moviesId'].'/documents/'.$documentId, $headers, [ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ 'data' => [ 'title' => 'Updated Date Test', - ], + ] ]); $updatedAtSecond = $document['body']['$updatedAt']; @@ -3158,12 +3164,12 @@ trait DatabasesBase \sleep(1); - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$data['databaseId'].'/collections/'.$data['moviesId'].'/documents/'.$documentId, $headers, [ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ 'data' => [ 'title' => 'Again Updated Date Test', '$createdAt' => '2022-08-01 13:09:23.040', // $createdAt is not updatable - '$updatedAt' => '2022-08-01 13:09:23.050', // system will update it not api - ], + '$updatedAt' => '2022-08-01 13:09:23.050' // system will update it not api + ] ]); $this->assertEquals($document['body']['title'], 'Again Updated Date Test'); @@ -3182,7 +3188,7 @@ trait DatabasesBase $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'Empty Permissions', @@ -3192,10 +3198,10 @@ trait DatabasesBase $databaseId = $database['body']['$id']; // Create collection - $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -3214,10 +3220,10 @@ trait DatabasesBase $moviesId = $movies['body']['$id']; // create attribute - $title = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/attributes/string', array_merge([ + $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'title', 'size' => 256, @@ -3230,7 +3236,7 @@ trait DatabasesBase sleep(2); // add document - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3254,20 +3260,20 @@ trait DatabasesBase $this->assertContains(Permission::delete(Role::any()), $document['body']['$permissions']); // Send only read permission - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'permissions' => [ Permission::read(Role::user(ID::custom($this->getUser()['$id']))), - ], + ] ]); $this->assertEquals(200, $document['headers']['status-code']); $this->assertCount(1, $document['body']['$permissions']); // Send only mutation permissions - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents/'.$id, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3285,7 +3291,7 @@ trait DatabasesBase } // remove collection - $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$moviesId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $moviesId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3303,39 +3309,39 @@ trait DatabasesBase /** * Test for SUCCESS */ - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), - 'name' => 'Boolean', + 'name' => 'Boolean' ]); $this->assertEquals(201, $collection['headers']['status-code']); $collectionId = $collection['body']['$id']; - $true = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean', array_merge([ + $true = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'true', 'required' => false, - 'default' => true, + 'default' => true ]); $this->assertEquals(202, $true['headers']['status-code']); - $false = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean', array_merge([ + $false = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'false', 'required' => false, - 'default' => false, + 'default' => false ]); $this->assertEquals(202, $false['headers']['status-code']); @@ -3348,10 +3354,10 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - $person = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => 'person', 'name' => 'person', @@ -3366,10 +3372,10 @@ trait DatabasesBase $this->assertEquals(201, $person['headers']['status-code']); - $library = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $library = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => 'library', 'name' => 'library', @@ -3383,10 +3389,10 @@ trait DatabasesBase $this->assertEquals(201, $library['headers']['status-code']); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'fullName', 'size' => 255, @@ -3395,10 +3401,10 @@ trait DatabasesBase sleep(1); // Wait for worker - $relation = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes/relationship', array_merge([ + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => 'library', 'type' => Database::RELATION_ONE_TO_ONE, @@ -3409,10 +3415,10 @@ trait DatabasesBase sleep(1); // Wait for worker - $libraryName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$library['body']['$id'].'/attributes/string', array_merge([ + $libraryName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $library['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'libraryName', 'size' => 255, @@ -3427,10 +3433,10 @@ trait DatabasesBase $this->assertEquals('relationship', $relation['body']['type']); $this->assertEquals('processing', $relation['body']['status']); - $attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes', array_merge([ + $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $attributes['headers']['status-code']); @@ -3445,7 +3451,7 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$person['body']['$id']}/attributes/library", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $attribute['headers']['status-code']); @@ -3459,7 +3465,7 @@ trait DatabasesBase $this->assertEquals('person', $attribute['body']['twoWayKey']); $this->assertEquals(Database::RELATION_MUTATE_CASCADE, $attribute['body']['onDelete']); - $person1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ + $person1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3477,13 +3483,13 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); // Create without nested ID - $person2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ + $person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3497,7 +3503,7 @@ trait DatabasesBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals('Library 2', $person2['body']['library']['libraryName']); @@ -3514,21 +3520,21 @@ trait DatabasesBase $this->assertArrayNotHasKey('$internalId', $person1['body']); $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ 'equal("library", "library1")', - 'select(["fullName","library.*"])', - ], + 'select(["fullName","library.*"])' + ] ]); $this->assertEquals(1, $documents['body']['total']); $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); $this->assertArrayHasKey('fullName', $documents['body']['documents'][0]); - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents', array_merge([ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3540,10 +3546,10 @@ trait DatabasesBase $this->assertEquals(400, $documents['headers']['status-code']); $this->assertEquals('Invalid query: Cannot query nested attribute on: library', $documents['body']['message']); - $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/attributes/library', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/library', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); sleep(2); @@ -3553,12 +3559,12 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$person['body']['$id']}/attributes/library", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(404, $attribute['headers']['status-code']); - $person1 = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$person['body']['$id'].'/documents/'.$person1['body']['$id'], array_merge([ + $person1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/' . $person1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3566,10 +3572,10 @@ trait DatabasesBase $this->assertArrayNotHasKey('library', $person1['body']); //Test Deletion of related twoKey - $attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$library['body']['$id'].'/attributes', array_merge([ + $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $library['body']['$id'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $attributes['headers']['status-code']); @@ -3593,10 +3599,10 @@ trait DatabasesBase $libraryCollection = $data['libraryCollection']; // One person can own several libraries - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$personCollection.'/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $personCollection . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => 'library', 'type' => Database::RELATION_ONE_TO_MANY, @@ -3607,20 +3613,20 @@ trait DatabasesBase sleep(1); - $libraryAttributesResponse = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$libraryCollection.'/attributes', array_merge([ + $libraryAttributesResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertIsArray($libraryAttributesResponse['body']['attributes']); $this->assertEquals(2, $libraryAttributesResponse['body']['total']); $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['attributes'][1]['key']); - $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$libraryCollection, array_merge([ + $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertIsArray($libraryCollectionResponse['body']['attributes']); @@ -3629,7 +3635,7 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$personCollection}/attributes/libraries", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $attribute['headers']['status-code']); @@ -3643,7 +3649,7 @@ trait DatabasesBase $this->assertEquals('person_one_to_many', $attribute['body']['twoWayKey']); $this->assertEquals('restrict', $attribute['body']['onDelete']); - $person2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$personCollection.'/documents', array_merge([ + $person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $personCollection . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3668,21 +3674,21 @@ trait DatabasesBase Permission::delete(Role::any()), ], 'libraryName' => 'Library 11', - ], + ] ], ], 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), - ], + ] ]); $this->assertEquals(201, $person2['headers']['status-code']); $this->assertArrayHasKey('libraries', $person2['body']); $this->assertEquals(2, count($person2['body']['libraries'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$personCollection.'/documents/'.$person2['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $personCollection . '/documents/' . $person2['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3692,7 +3698,7 @@ trait DatabasesBase $this->assertArrayHasKey('libraries', $response['body']); $this->assertEquals(2, count($response['body']['libraries'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$libraryCollection.'/documents/library11', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection . '/documents/library11', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3701,10 +3707,10 @@ trait DatabasesBase $this->assertArrayHasKey('person_one_to_many', $response['body']); $this->assertEquals('person10', $response['body']['person_one_to_many']['$id']); - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$personCollection.'/attributes/libraries/relationship', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $personCollection . '/attributes/libraries/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'onDelete' => Database::RELATION_MUTATE_CASCADE, ]); @@ -3714,7 +3720,7 @@ trait DatabasesBase $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$personCollection}/attributes/libraries", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $attribute['headers']['status-code']); @@ -3738,10 +3744,10 @@ trait DatabasesBase $databaseId = $data['databaseId']; // Create album collection - $albums = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $albums = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Albums', @@ -3753,10 +3759,10 @@ trait DatabasesBase ]); // Create album name attribute - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 255, @@ -3764,10 +3770,10 @@ trait DatabasesBase ]); // Create artist collection - $artists = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $artists = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Artists', @@ -3779,10 +3785,10 @@ trait DatabasesBase ]); // Create artist name attribute - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$artists['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $artists['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 255, @@ -3790,10 +3796,10 @@ trait DatabasesBase ]); // Create relationship - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/attributes/relationship', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $artists['body']['$id'], 'type' => Database::RELATION_MANY_TO_ONE, @@ -3820,7 +3826,7 @@ trait DatabasesBase ]; // Create album - $album = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/documents', array_merge([ + $album = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3842,7 +3848,7 @@ trait DatabasesBase $this->assertEquals($permissions, $album['body']['$permissions']); $this->assertEquals($permissions, $album['body']['artist']['$permissions']); - $album = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$albums['body']['$id'].'/documents/album1', array_merge([ + $album = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/documents/album1', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3854,7 +3860,7 @@ trait DatabasesBase $this->assertEquals($permissions, $album['body']['$permissions']); $this->assertEquals($permissions, $album['body']['artist']['$permissions']); - $artist = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$artists['body']['$id'].'/documents/'.$album['body']['artist']['$id'], array_merge([ + $artist = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $artists['body']['$id'] . '/documents/' . $album['body']['artist']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3882,10 +3888,10 @@ trait DatabasesBase $databaseId = $data['databaseId']; // Create sports collection - $sports = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $sports = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Sports', @@ -3897,10 +3903,10 @@ trait DatabasesBase ]); // Create sport name attribute - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 255, @@ -3908,10 +3914,10 @@ trait DatabasesBase ]); // Create player collection - $players = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $players = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Players', @@ -3923,10 +3929,10 @@ trait DatabasesBase ]); // Create player name attribute - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$players['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $players['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 255, @@ -3934,10 +3940,10 @@ trait DatabasesBase ]); // Create relationship - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/attributes/relationship', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $players['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, @@ -3965,7 +3971,7 @@ trait DatabasesBase ]; // Create sport - $sport = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/documents', array_merge([ + $sport = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3981,7 +3987,7 @@ trait DatabasesBase [ '$id' => 'player2', 'name' => 'Player 2', - ], + ] ], ], ]); @@ -3995,7 +4001,7 @@ trait DatabasesBase $this->assertEquals($permissions, $sport['body']['players'][0]['$permissions']); $this->assertEquals($permissions, $sport['body']['players'][1]['$permissions']); - $sport = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$sports['body']['$id'].'/documents/sport1', array_merge([ + $sport = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/documents/sport1', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -4009,7 +4015,7 @@ trait DatabasesBase $this->assertEquals($permissions, $sport['body']['players'][0]['$permissions']); $this->assertEquals($permissions, $sport['body']['players'][1]['$permissions']); - $player = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$players['body']['$id'].'/documents/'.$sport['body']['players'][0]['$id'], array_merge([ + $player = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $players['body']['$id'] . '/documents/' . $sport['body']['players'][0]['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -4034,7 +4040,7 @@ trait DatabasesBase */ public function testValidateOperators(array $data): void { - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -4052,21 +4058,21 @@ trait DatabasesBase $this->assertEquals('Stevie Wonder', $response['body']['documents'][0]['fullName']); $this->assertEquals(2, count($response['body']['documents'][0]['libraries'])); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ 'isNotNull("$id")', 'isNull("fullName")', - 'select(["fullName"])', + 'select(["fullName"])' ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, count($response['body']['documents'])); $this->assertEquals(null, $response['body']['documents'][0]['fullName']); - $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); + $this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]); } /** @@ -4074,20 +4080,20 @@ trait DatabasesBase */ public function testSelectsQueries(array $data): void { - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ 'equal("fullName", "Stevie Wonder")', - 'select(["fullName"])', + 'select(["fullName"])' ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -4099,12 +4105,12 @@ trait DatabasesBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$data['databaseId'].'/collections/'.$data['personCollection'].'/documents/'.$document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - 'select(["fullName", "$id"])', + 'select(["fullName", "$id"])' ], ]); @@ -4115,20 +4121,18 @@ trait DatabasesBase /** * @depends testCreateDatabase - * - * @param array $data + * @param array $data * @return void - * * @throws \Exception */ public function testUpdateWithExistingRelationships(array $data): void { $databaseId = $data['databaseId']; - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Collection1', @@ -4139,10 +4143,10 @@ trait DatabasesBase ], ]); - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Collection2', @@ -4156,42 +4160,42 @@ trait DatabasesBase $collection1 = $collection1['body']['$id']; $collection2 = $collection2['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1.'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => '49', 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection2.'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2 . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => '49', 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1.'/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $collection2, 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, - 'key' => 'collection2', + 'key' => 'collection2' ]); sleep(1); - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/documents', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ @@ -4204,9 +4208,9 @@ trait DatabasesBase ], ]); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1.'/documents/'.$document['body']['$id'], array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1 . '/documents/' . $document['body']['$id'], array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ 'data' => [ 'name' => 'Document 1 Updated', diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php index 947b0ed7fe..17059adf88 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php @@ -2,9 +2,9 @@ namespace Tests\E2E\Services\Databases; -use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Client; use Tests\E2E\Scopes\SideConsole; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -32,7 +32,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -53,7 +53,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still create collections */ - $database = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId, array_merge([ + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -63,7 +63,7 @@ class DatabasesConsoleClientTest extends Scope $this->assertFalse($database['body']['enabled']); - $tvShows = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $tvShows = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -86,8 +86,7 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * - * @param array $data + * @param array $data */ public function testListCollection(array $data) { @@ -96,10 +95,10 @@ class DatabasesConsoleClientTest extends Scope */ $databaseId = $data['databaseId']; - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders())); $this->assertEquals(200, $collections['headers']['status-code']); @@ -108,8 +107,7 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * - * @param array $data + * @param array $data */ public function testGetCollection(array $data) { @@ -119,7 +117,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still call get collection */ - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$moviesCollectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $moviesCollectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -132,8 +130,7 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * - * @param array $data + * @param array $data */ public function testUpdateCollection(array $data) { @@ -143,12 +140,12 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still call update collection */ - $collection = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$moviesCollectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $moviesCollectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Movies Updated', - 'enabled' => false, + 'enabled' => false ]); $this->assertEquals(200, $collection['headers']['status-code']); @@ -159,8 +156,7 @@ class DatabasesConsoleClientTest extends Scope /** * @depends testCreateCollection - * - * @param array $data + * @param array $data */ public function testDeleteCollection(array $data) { @@ -170,13 +166,13 @@ class DatabasesConsoleClientTest extends Scope /** * Test When database is disabled but can still call Delete collection */ - $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$tvShowsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $tvShowsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals($response['body'], ''); + $this->assertEquals($response['body'], ""); } /** @@ -188,11 +184,12 @@ class DatabasesConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/usage', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '32h', + 'range' => '32h' ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -200,11 +197,12 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/usage', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -214,6 +212,7 @@ class DatabasesConsoleClientTest extends Scope $this->assertIsArray($response['body']['collectionsTotal']); } + /** * @depends testCreateCollection */ @@ -223,20 +222,21 @@ class DatabasesConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/usage', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '32h', + 'range' => '32h' ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/randomCollectionId/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/randomCollectionId/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -244,11 +244,11 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(count($response['body']), 2); @@ -265,7 +265,7 @@ class DatabasesConsoleClientTest extends Scope /** * Test for SUCCESS */ - $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -274,11 +274,11 @@ class DatabasesConsoleClientTest extends Scope $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 1, + 'limit' => 1 ]); $this->assertEquals(200, $logs['headers']['status-code']); @@ -286,23 +286,23 @@ class DatabasesConsoleClientTest extends Scope $this->assertLessThanOrEqual(1, count($logs['body']['logs'])); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'offset' => 1, + 'offset' => 1 ]); $this->assertEquals(200, $logs['headers']['status-code']); $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['moviesId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'offset' => 1, - 'limit' => 1, + 'limit' => 1 ]); $this->assertEquals(200, $logs['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index b5abaebfad..743df9e53a 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -21,22 +21,23 @@ class DatabasesCustomClientTest extends Scope /** * Test for SUCCESS */ + $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'databaseId' => ID::unique(), - 'name' => 'Test Database', + 'name' => 'Test Database' ]); $databaseId = $database['body']['$id']; // Collection aliases write to create, update, delete - $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', @@ -52,10 +53,10 @@ class DatabasesCustomClientTest extends Scope $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/attributes/string', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'title', 'size' => 256, @@ -67,7 +68,7 @@ class DatabasesCustomClientTest extends Scope $this->assertEquals(202, $response['headers']['status-code']); // Document aliases write to update, delete - $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -77,7 +78,7 @@ class DatabasesCustomClientTest extends Scope ], 'permissions' => [ Permission::write(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertNotContains(Permission::create(Role::user($this->getUser()['$id'])), $document1['body']['$permissions']); @@ -89,7 +90,7 @@ class DatabasesCustomClientTest extends Scope */ // Document does not allow create permission - $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -99,7 +100,7 @@ class DatabasesCustomClientTest extends Scope ], 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals(400, $document2['headers']['status-code']); @@ -113,7 +114,7 @@ class DatabasesCustomClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); @@ -122,7 +123,7 @@ class DatabasesCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::custom('permissionCheckDatabase'), 'name' => 'Test Database', @@ -132,10 +133,10 @@ class DatabasesCustomClientTest extends Scope $databaseId = $database['body']['$id']; // Create collection - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('permissionCheck'), 'name' => 'permissionCheck', @@ -145,10 +146,10 @@ class DatabasesCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); // Add attribute to collection - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/permissionCheck/attributes/string', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/permissionCheck/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 255, @@ -160,10 +161,10 @@ class DatabasesCustomClientTest extends Scope sleep(2); // Creating document by server, give read permission to our user + some other user - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/permissionCheck/documents', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/permissionCheck/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'documentId' => ID::custom('permissionCheckDocument'), 'data' => [ @@ -181,43 +182,44 @@ class DatabasesCustomClientTest extends Scope // Update document // This is the point of this test. We should be allowed to do this action, and it should not fail on permission check - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ 'name' => 'AppwriteExpert', - ], + ] ]); $this->assertEquals(200, $response['headers']['status-code']); // Get name of the document, should be the new one - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/permissionCheck/documents/permissionCheckDocument', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals('AppwriteExpert', $response['body']['name']); + $this->assertEquals("AppwriteExpert", $response['body']['name']); // Cleanup to prevent collision with other tests // Delete collection - $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/permissionCheck', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/permissionCheck', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $response['headers']['status-code']); + // Wait for database worker to finish deleting collection sleep(2); // Make sure collection has been deleted - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/permissionCheck', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/permissionCheck', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(404, $response['headers']['status-code']); @@ -226,22 +228,24 @@ class DatabasesCustomClientTest extends Scope public function testUpdateTwoWayRelationship(): void { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'databaseId' => ID::unique(), - 'name' => 'Test Database', + 'name' => 'Test Database' ]); $databaseId = $database['body']['$id']; + // Creating collection 1 - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'level1', @@ -251,14 +255,14 @@ class DatabasesCustomClientTest extends Scope Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); // Creating collection 2 - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'level2', @@ -268,41 +272,41 @@ class DatabasesCustomClientTest extends Scope Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); \sleep(2); // Creating two way relationship between collection 1 and collection 2 from collection 1 - $relation = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/attributes/relationship', array_merge([ + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $collection2['body']['$id'], 'type' => 'oneToMany', 'twoWay' => true, 'onDelete' => 'cascade', 'key' => $collection2['body']['$id'], - 'twoWayKey' => $collection1['body']['$id'], + 'twoWayKey' => $collection1['body']['$id'] ]); \sleep(3); // Update relation from collection 2 to on delete restrict - $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/attributes/'.$collection1['body']['$id'].'/relationship', array_merge([ + $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/' . $collection1['body']['$id'] . '/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'onDelete' => 'restrict', ]); // Fetching attributes after updating relation to compare - $collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'], [ + $collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]); $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; @@ -319,7 +323,7 @@ class DatabasesCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'databaseId' => ID::unique(), 'name' => ID::unique(), @@ -328,10 +332,10 @@ class DatabasesCustomClientTest extends Scope $databaseId = $database['body']['$id']; // Creating collection 1 - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection1'), 'name' => ID::custom('collection1'), @@ -340,27 +344,27 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ], + ] ]); // Creating collection 2 - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), 'documentSecurity' => false, 'permissions' => [ Permission::read(Role::user($userId)), - ], + ] ]); - $collection3 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), @@ -369,26 +373,26 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ], + ] ]); - $collection4 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection4'), 'name' => ID::custom('collection4'), 'documentSecurity' => false, 'permissions' => [ Permission::read(Role::user($userId)), - ], + ] ]); - $collection5 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection5 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection5'), 'name' => ID::custom('collection5'), @@ -397,115 +401,115 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ], + ] ]); // Creating one to one relationship from collection 1 to colletion 2 - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $collection2['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection2['body']['$id'], + 'key' => $collection2['body']['$id'] ]); // Creating one to one relationship from collection 2 to colletion 3 - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $collection3['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection3['body']['$id'], + 'key' => $collection3['body']['$id'] ]); // Creating one to one relationship from collection 3 to colletion 4 - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection3['body']['$id'].'/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $collection4['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection4['body']['$id'], + 'key' => $collection4['body']['$id'] ]); // Creating one to one relationship from collection 4 to colletion 5 - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection4['body']['$id'].'/attributes/relationship', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection4['body']['$id'] . '/attributes/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'relatedCollectionId' => $collection5['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', - 'key' => $collection5['body']['$id'], + 'key' => $collection5['body']['$id'] ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'Title', + 'key' => "Title", 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'Rating', + 'key' => "Rating", 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection3['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'Rating', + 'key' => "Rating", 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection4['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection4['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'Rating', + 'key' => "Rating", 'size' => 100, 'required' => false, 'array' => false, 'default' => null, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection5['body']['$id'].'/attributes/string', array_merge([ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection5['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'Rating', + 'key' => "Rating", 'size' => 100, 'required' => false, 'array' => false, @@ -514,10 +518,10 @@ class DatabasesCustomClientTest extends Scope \sleep(2); // Creating parent document with a child reference to test the permissions - $parentDocument = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents', array_merge([ + $parentDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'documentId' => ID::custom($collection1['body']['$id']), 'data' => [ @@ -533,17 +537,17 @@ class DatabasesCustomClientTest extends Scope 'Rating' => '10', $collection5['body']['$id'] => [ '$id' => ID::custom($collection5['body']['$id']), - 'Rating' => '10', - ], - ], - ], - ], - ], + 'Rating' => '10' + ] + ] + ] + ] + ] ]); $this->assertEquals(201, $parentDocument['headers']['status-code']); // This is the point of the test. We should not need any authorization permission to update the document with same data. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -561,21 +565,21 @@ class DatabasesCustomClientTest extends Scope 'Rating' => '10', $collection5['body']['$id'] => [ '$id' => $collection5['body']['$id'], - 'Rating' => '10', - ], - ], - ], - ], - ], + 'Rating' => '10' + ] + ] + ] + ] + ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($parentDocument['body'], $response['body']); // Giving update permission of collection 3 to user. - $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/collection3', array_merge([ + $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection3', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), @@ -585,11 +589,11 @@ class DatabasesCustomClientTest extends Scope Permission::read(Role::user($userId)), Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), - ], + ] ]); // This is the point of this test. We should be allowed to do this action, and it should not fail on permission check - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -606,19 +610,19 @@ class DatabasesCustomClientTest extends Scope 'Rating' => '10', $collection5['body']['$id'] => [ '$id' => ID::custom($collection5['body']['$id']), - 'Rating' => '11', - ], - ], - ], - ], - ], + 'Rating' => '11' + ] + ] + ] + ] + ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(11, $response['body'][$collection2['body']['$id']]['collection3']['Rating']); // We should not be allowed to update the document as we do not have permission for collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -628,29 +632,29 @@ class DatabasesCustomClientTest extends Scope '$id' => ID::custom($collection2['body']['$id']), 'Rating' => '11', $collection3['body']['$id'] => null, - ], - ], + ] + ] ]); $this->assertEquals(401, $response['headers']['status-code']); // We should not be allowed to update the document as we do not have permission for collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection2['body']['$id'].'/documents/'.$collection2['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/documents/' . $collection2['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ 'Rating' => '11', - ], + ] ]); $this->assertEquals(401, $response['headers']['status-code']); // Removing update permission from collection 3. - $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/collection3', array_merge([ + $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection3', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), @@ -659,14 +663,14 @@ class DatabasesCustomClientTest extends Scope Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ], + ] ]); // Giving update permission to collection 2. - $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/collection2', array_merge([ + $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), @@ -676,25 +680,25 @@ class DatabasesCustomClientTest extends Scope Permission::update(Role::user($userId)), Permission::read(Role::user($userId)), Permission::delete(Role::user($userId)), - ], + ] ]); // Creating collection 3 new document - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection3['body']['$id'].'/documents', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'documentId' => ID::custom('collection3Doc1'), 'data' => [ - 'Rating' => '20', - ], + 'Rating' => '20' + ] ]); $this->assertEquals(201, $response['headers']['status-code']); // We should be allowed to link a new document from collection 3 to collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -703,14 +707,15 @@ class DatabasesCustomClientTest extends Scope $collection2['body']['$id'] => [ '$id' => ID::custom($collection2['body']['$id']), $collection3['body']['$id'] => 'collection3Doc1', - ], - ], + ] + ] ]); $this->assertEquals(200, $response['headers']['status-code']); + // We should be allowed to link and create a new document from collection 3 to collection 2. - $response = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection1['body']['$id'].'/documents/'.$collection1['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -719,10 +724,10 @@ class DatabasesCustomClientTest extends Scope $collection2['body']['$id'] => [ '$id' => ID::custom($collection2['body']['$id']), $collection3['body']['$id'] => [ - '$id' => ID::custom('collection3Doc2'), + '$id' => ID::custom('collection3Doc2') ], - ], - ], + ] + ] ]); $this->assertEquals(200, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 57b609c33a..648a4de800 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -3,10 +3,10 @@ namespace Tests\E2E\Services\Databases; use Appwrite\Extend\Exception as AppwriteException; -use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Tests\E2E\Client; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -22,7 +22,7 @@ class DatabasesCustomServerTest extends Scope $test1 = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::custom('first'), 'name' => 'Test 1', @@ -34,7 +34,7 @@ class DatabasesCustomServerTest extends Scope $test2 = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::custom('second'), 'name' => 'Test 2', @@ -124,7 +124,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['databases'][0]['$id'].'")'], + 'queries' => ['cursorAfter("' . $base['body']['databases'][0]['$id'] . '")'], ]); $this->assertCount(1, $databases['body']['databases']); @@ -134,7 +134,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['databases'][1]['$id'].'")'], + 'queries' => ['cursorAfter("' . $base['body']['databases'][1]['$id'] . '")'], ]); $this->assertCount(0, $databases['body']['databases']); @@ -152,7 +152,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['databases'][1]['$id'].'")'], + 'queries' => ['cursorBefore("' . $base['body']['databases'][1]['$id'] . '")'], ]); $this->assertCount(1, $databases['body']['databases']); @@ -162,7 +162,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['databases'][0]['$id'].'")'], + 'queries' => ['cursorBefore("' . $base['body']['databases'][0]['$id'] . '")'], ]); $this->assertCount(0, $databases['body']['databases']); @@ -175,7 +175,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'first', + 'search' => 'first' ]); $this->assertEquals(1, $databases['body']['total']); @@ -185,7 +185,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Test', + 'search' => 'Test' ]); $this->assertEquals(2, $databases['body']['total']); @@ -196,7 +196,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Nonexistent', + 'search' => 'Nonexistent' ]); $this->assertEquals(0, $databases['body']['total']); @@ -217,14 +217,13 @@ class DatabasesCustomServerTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', 'databaseId' => ID::custom('first'), ]); $this->assertEquals(409, $response['headers']['status-code']); - return ['databaseId' => $test1['body']['$id']]; } @@ -237,17 +236,16 @@ class DatabasesCustomServerTest extends Scope /** * Test for SUCCESS */ - $database = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId, [ + $database = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]); $this->assertEquals(200, $database['headers']['status-code']); $this->assertEquals($databaseId, $database['body']['$id']); $this->assertEquals('Test 1', $database['body']['name']); $this->assertEquals(true, $database['body']['enabled']); - return ['databaseId' => $database['body']['$id']]; } @@ -258,10 +256,10 @@ class DatabasesCustomServerTest extends Scope { $databaseId = $data['databaseId']; - $database = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId, [ + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'name' => 'Test 1 Updated', 'enabled' => false, @@ -272,12 +270,12 @@ class DatabasesCustomServerTest extends Scope $this->assertFalse($database['body']['enabled']); // Now update the database without the passing the enabled parameter - $database = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId, [ + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'name' => 'Test 1', + 'name' => 'Test 1' ]); $this->assertEquals(200, $database['headers']['status-code']); @@ -292,19 +290,19 @@ class DatabasesCustomServerTest extends Scope { $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals('', $response['body']); + $this->assertEquals("", $response['body']); // Try to get the collection and check if it has been deleted - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); @@ -315,7 +313,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -328,10 +326,10 @@ class DatabasesCustomServerTest extends Scope /** * Test for SUCCESS */ - $test1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $test1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', 'collectionId' => ID::custom('first'), @@ -344,10 +342,10 @@ class DatabasesCustomServerTest extends Scope 'documentSecurity' => true, ]); - $test2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $test2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 2', 'collectionId' => ID::custom('second'), @@ -360,7 +358,7 @@ class DatabasesCustomServerTest extends Scope 'documentSecurity' => true, ]); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -373,41 +371,41 @@ class DatabasesCustomServerTest extends Scope $base = array_reverse($collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => ['limit(1)'] ]); $this->assertEquals(200, $collections['headers']['status-code']); $this->assertCount(1, $collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => ['offset(1)'] ]); $this->assertEquals(200, $collections['headers']['status-code']); $this->assertCount(1, $collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("enabled", true)'], + 'queries' => ['equal("enabled", true)'] ]); $this->assertEquals(200, $collections['headers']['status-code']); $this->assertCount(2, $collections['body']['collections']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("enabled", false)'], + 'queries' => ['equal("enabled", false)'] ]); $this->assertEquals(200, $collections['headers']['status-code']); @@ -416,7 +414,7 @@ class DatabasesCustomServerTest extends Scope /** * Test for Order */ - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -430,26 +428,26 @@ class DatabasesCustomServerTest extends Scope /** * Test for After */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['collections'][0]['$id'].'")'], + 'queries' => ['cursorAfter("' . $base['body']['collections'][0]['$id'] . '")'], ]); $this->assertCount(1, $collections['body']['collections']); $this->assertEquals($base['body']['collections'][1]['$id'], $collections['body']['collections'][0]['$id']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$base['body']['collections'][1]['$id'].'")'], + 'queries' => ['cursorAfter("' . $base['body']['collections'][1]['$id'] . '")'], ]); $this->assertCount(0, $collections['body']['collections']); @@ -458,26 +456,26 @@ class DatabasesCustomServerTest extends Scope /** * Test for Before */ - $base = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['collections'][1]['$id'].'")'], + 'queries' => ['cursorBefore("' . $base['body']['collections'][1]['$id'] . '")'], ]); $this->assertCount(1, $collections['body']['collections']); $this->assertEquals($base['body']['collections'][0]['$id'], $collections['body']['collections'][0]['$id']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$base['body']['collections'][0]['$id'].'")'], + 'queries' => ['cursorBefore("' . $base['body']['collections'][0]['$id'] . '")'], ]); $this->assertCount(0, $collections['body']['collections']); @@ -486,32 +484,32 @@ class DatabasesCustomServerTest extends Scope /** * Test for Search */ - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'first', + 'search' => 'first' ]); $this->assertEquals(1, $collections['body']['total']); $this->assertEquals('first', $collections['body']['collections'][0]['$id']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Test', + 'search' => 'Test' ]); $this->assertEquals(2, $collections['body']['total']); $this->assertEquals('Test 1', $collections['body']['collections'][0]['name']); $this->assertEquals('Test 2', $collections['body']['collections'][1]['name']); - $collections = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Nonexistent', + 'search' => 'Nonexistent' ]); $this->assertEquals(0, $collections['body']['total']); @@ -519,7 +517,7 @@ class DatabasesCustomServerTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -529,10 +527,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); // This collection already exists - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', 'collectionId' => ID::custom('first'), @@ -546,7 +544,6 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(409, $response['headers']['status-code']); - return [ 'databaseId' => $databaseId, 'collectionId' => $test1['body']['$id'], @@ -561,10 +558,10 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders())); $this->assertEquals(200, $collection['headers']['status-code']); @@ -581,13 +578,13 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $collection = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1 Updated', - 'enabled' => false, + 'enabled' => false ]); $this->assertEquals(200, $collection['headers']['status-code']); @@ -597,10 +594,11 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testListCollections + * @depends testListCollections */ public function testCreateEncryptedAttribute(array $data): void { + $databaseId = $data['databaseId']; /** @@ -608,10 +606,10 @@ class DatabasesCustomServerTest extends Scope */ // Create collection - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Encrypted Actors Data', @@ -630,22 +628,23 @@ class DatabasesCustomServerTest extends Scope /** * Test for creating encrypted attributes */ - $attributesPath = '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes'; - $firstName = $this->client->call(Client::METHOD_POST, $attributesPath.'/string', array_merge([ + $attributesPath = '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes'; + + $firstName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'firstName', 'size' => 256, 'required' => true, ]); - $lastName = $this->client->call(Client::METHOD_POST, $attributesPath.'/string', array_merge([ + $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'lastName', 'size' => 256, @@ -653,6 +652,7 @@ class DatabasesCustomServerTest extends Scope 'encrypt' => true, ]); + /** * Check status of every attribute */ @@ -668,10 +668,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Creating document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'documentId' => ID::unique(), 'data' => [ @@ -686,10 +686,10 @@ class DatabasesCustomServerTest extends Scope ]); // Check document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents/'.$document['body']['$id'], array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents/' . $document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $document['headers']['status-code']); @@ -702,7 +702,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -716,10 +716,10 @@ class DatabasesCustomServerTest extends Scope */ // Create collection - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -735,30 +735,30 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $actors['headers']['status-code']); $this->assertEquals($actors['body']['name'], 'Actors'); - $firstName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/string', array_merge([ + $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'firstName', 'size' => 256, 'required' => true, ]); - $lastName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/string', array_merge([ + $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'lastName', 'size' => 256, 'required' => true, ]); - $unneeded = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/string', array_merge([ + $unneeded = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'unneeded', 'size' => 256, @@ -769,16 +769,16 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Creating document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'lorem', 'lastName' => 'ipsum', - 'unneeded' => 'dolor', + 'unneeded' => 'dolor' ], 'permissions' => [ Permission::read(Role::any()), @@ -787,10 +787,10 @@ class DatabasesCustomServerTest extends Scope ], ]); - $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'key_lastName', 'type' => 'key', @@ -802,10 +802,10 @@ class DatabasesCustomServerTest extends Scope // Wait for database worker to finish creating index sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $unneededId = $unneeded['body']['key']; @@ -820,10 +820,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($collection['body']['indexes'][0]['key'], $index['body']['key']); // Delete attribute - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/attributes/'.$unneededId, array_merge([ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actors ['body']['$id'] . '/attributes/' . $unneededId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $attribute['headers']['status-code']); @@ -831,18 +831,18 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Check document to ensure cache is purged on schema change - $document = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'].'/documents/'.$document['body']['$id'], array_merge([ + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents/' . $document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertNotContains($unneededId, $document['body']); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $this->assertEquals(200, $collection['headers']['status-code']); @@ -854,7 +854,7 @@ class DatabasesCustomServerTest extends Scope return [ 'collectionId' => $actors['body']['$id'], 'key' => $index['body']['key'], - 'databaseId' => $databaseId, + 'databaseId' => $databaseId ]; } @@ -864,10 +864,10 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndex($data): array { $databaseId = $data['databaseId']; - $index = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/indexes/'.$data['key'], array_merge([ + $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes/' . $data['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $index['headers']['status-code']); @@ -875,10 +875,10 @@ class DatabasesCustomServerTest extends Scope // Wait for database worker to finish deleting index sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['collectionId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $this->assertCount(0, $collection['body']['indexes']); @@ -892,20 +892,20 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndexOnDeleteAttribute($data) { $databaseId = $data['databaseId']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/string', array_merge([ + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'attribute1', 'size' => 16, 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/string', array_merge([ + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'attribute2', 'size' => 16, @@ -919,10 +919,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); - $index1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/indexes', array_merge([ + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'index1', 'type' => 'key', @@ -930,10 +930,10 @@ class DatabasesCustomServerTest extends Scope 'orders' => ['ASC', 'ASC'], ]); - $index2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/indexes', array_merge([ + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'index2', 'type' => 'key', @@ -948,10 +948,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/'.$attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -959,10 +959,10 @@ class DatabasesCustomServerTest extends Scope // wait for database worker to complete sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$data['collectionId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -974,10 +974,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['collectionId'].'/attributes/'.$attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -990,7 +990,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -999,10 +999,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'TestCleanupDuplicateIndexOnDeleteAttribute', @@ -1020,20 +1020,20 @@ class DatabasesCustomServerTest extends Scope $collectionId = $collection['body']['$id']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'attribute1', 'size' => 16, 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'attribute2', 'size' => 16, @@ -1047,10 +1047,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); - $index1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'index1', 'type' => 'key', @@ -1058,10 +1058,10 @@ class DatabasesCustomServerTest extends Scope 'orders' => ['ASC', 'ASC'], ]); - $index2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'index2', 'type' => 'key', @@ -1076,10 +1076,10 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -1087,10 +1087,10 @@ class DatabasesCustomServerTest extends Scope // wait for database worker to complete sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -1102,10 +1102,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($attribute2['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $deleted['headers']['status-code']); @@ -1120,7 +1120,7 @@ class DatabasesCustomServerTest extends Scope $collectionId = $data['collectionId']; // Add Documents to the collection - $document1 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1136,7 +1136,7 @@ class DatabasesCustomServerTest extends Scope ], ]); - $document2 = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1165,19 +1165,19 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($document2['body']['lastName'], 'Jackson'); // Delete the actors collection - $response = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals($response['body'], ''); + $this->assertEquals($response['body'], ""); // Try to get the collection and check if it has been deleted - $response = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); @@ -1242,7 +1242,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -1251,10 +1251,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('attributeRowWidthLimit'), 'name' => 'attributeRowWidthLimit', @@ -1274,10 +1274,10 @@ class DatabasesCustomServerTest extends Scope // Add wide string attributes to approach row width limit for ($i = 0; $i < 15; $i++) { - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => "attribute{$i}", 'size' => 1024, @@ -1289,10 +1289,10 @@ class DatabasesCustomServerTest extends Scope sleep(5); - $tooWide = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $tooWide = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'tooWide', 'size' => 1024, @@ -1308,7 +1308,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'invalidDocumentDatabase', @@ -1317,10 +1317,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('testLimitException'), 'name' => 'testLimitException', @@ -1341,10 +1341,10 @@ class DatabasesCustomServerTest extends Scope // add unique attributes for indexing for ($i = 0; $i < 64; $i++) { // $this->assertEquals(true, static::getDatabase()->createAttribute('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => "attribute{$i}", 'size' => 64, @@ -1356,10 +1356,10 @@ class DatabasesCustomServerTest extends Scope sleep(10); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -1370,7 +1370,7 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(0, $collection['body']['indexes']); foreach ($collection['body']['attributes'] as $attribute) { - $this->assertEquals('available', $attribute['status'], 'attribute: '.$attribute['key']); + $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); } // Test indexLimit = 64 @@ -1378,10 +1378,10 @@ class DatabasesCustomServerTest extends Scope // Add up to the limit, then check if the next index throws IndexLimitException for ($i = 0; $i < 59; $i++) { // $this->assertEquals(true, static::getDatabase()->createIndex('indexLimit', "index{$i}", Database::INDEX_KEY, ["test{$i}"], [16])); - $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => "key_attribute{$i}", 'type' => 'key', @@ -1394,10 +1394,10 @@ class DatabasesCustomServerTest extends Scope sleep(5); - $collection = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(200, $collection['headers']['status-code']); @@ -1407,10 +1407,10 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(64, $collection['body']['attributes']); $this->assertCount(59, $collection['body']['indexes']); - $tooMany = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/indexes', array_merge([ + $tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'tooMany', 'type' => 'key', @@ -1420,10 +1420,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $tooMany['headers']['status-code']); $this->assertEquals('Index limit exceeded', $tooMany['body']['message']); - $collection = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $collection = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $collection['headers']['status-code']); @@ -1434,7 +1434,7 @@ class DatabasesCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'updateAttributes', @@ -1442,13 +1442,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $database['headers']['status-code']); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::custom('updateAttributes'), - 'name' => 'updateAttributes', + 'name' => 'updateAttributes' ]); $this->assertEquals(201, $collection['headers']['status-code']); @@ -1458,14 +1458,14 @@ class DatabasesCustomServerTest extends Scope /** * Create String Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'string', 'size' => 1024, - 'required' => false, + 'required' => false ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1473,13 +1473,13 @@ class DatabasesCustomServerTest extends Scope /** * Create Email Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'email', - 'required' => false, + 'required' => false ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1487,13 +1487,13 @@ class DatabasesCustomServerTest extends Scope /** * Create IP Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'ip', - 'required' => false, + 'required' => false ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1501,13 +1501,13 @@ class DatabasesCustomServerTest extends Scope /** * Create URL Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'url', - 'required' => false, + 'required' => false ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1515,13 +1515,13 @@ class DatabasesCustomServerTest extends Scope /** * Create Integer Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'integer', - 'required' => false, + 'required' => false ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1529,50 +1529,50 @@ class DatabasesCustomServerTest extends Scope /** * Create Float Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'float', - 'required' => false, + 'required' => false ]); /** * Create Boolean Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'boolean', - 'required' => false, + 'required' => false ]); /** * Create Datetime Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'datetime', - 'required' => false, + 'required' => false ]); /** * Create Enum Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum', array_merge([ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'enum', 'required' => false, - 'elements' => ['lorem', 'ipsum'], + 'elements' => ['lorem', 'ipsum'] ]); $this->assertEquals(202, $attribute['headers']['status-code']); @@ -1581,10 +1581,11 @@ class DatabasesCustomServerTest extends Scope return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'collectionId' => $collectionId ]; } + /** * @depends testAttributeUpdate */ @@ -1594,72 +1595,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'lorem', + 'default' => 'lorem' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertEquals('lorem', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'ipsum', + 'default' => 'ipsum' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -1668,34 +1669,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'i am no boolean', - 'default' => 'dolor', + 'default' => 'dolor' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 123, + 'default' => 123 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, ]); @@ -1703,24 +1704,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'default' => 'ipsum', + 'default' => 'ipsum' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/string/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, - 'default' => 'ipsum', + 'default' => 'ipsum' ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -1736,72 +1737,73 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'torsten@appwrite.io', + 'default' => 'torsten@appwrite.io' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertEquals('torsten@appwrite.io', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('torsten@appwrite.io', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'eldad@appwrite.io', + 'default' => 'eldad@appwrite.io' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -1810,34 +1812,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', - 'default' => 'torsten@appwrite.io', + 'default' => 'torsten@appwrite.io' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'i am no email', + 'default' => 'i am no email' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, ]); @@ -1845,24 +1847,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'default' => 'ipsum', + 'default' => 'ipsum' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/email/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, - 'default' => 'torsten@appwrite.io', + 'default' => 'torsten@appwrite.io' ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -1878,72 +1880,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => '127.0.0.1', + 'default' => '127.0.0.1' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertEquals('127.0.0.1', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('127.0.0.1', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => '192.168.0.1', + 'default' => '192.168.0.1' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -1952,34 +1954,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', - 'default' => '127.0.0.1', + 'default' => '127.0.0.1' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'i am no ip', + 'default' => 'i am no ip' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, ]); @@ -1987,24 +1989,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'default' => '127.0.0.1', + 'default' => '127.0.0.1' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/ip/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, - 'default' => '127.0.0.1', + 'default' => '127.0.0.1' ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2020,72 +2022,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'http://appwrite.io', + 'default' => 'http://appwrite.io' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertEquals('http://appwrite.io', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('http://appwrite.io', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'https://appwrite.io', + 'default' => 'https://appwrite.io' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2094,34 +2096,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', - 'default' => 'https://appwrite.io', + 'default' => 'https://appwrite.io' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'i am no url', + 'default' => 'i am no url' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, ]); @@ -2129,24 +2131,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'default' => 'https://appwrite.io', + 'default' => 'https://appwrite.io' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/url/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, - 'default' => 'https://appwrite.io', + 'default' => 'https://appwrite.io' ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2162,23 +2164,23 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123, 'min' => 0, - 'max' => 1000, + 'max' => 1000 ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2186,36 +2188,36 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123, $attribute['default']); $this->assertEquals(0, $attribute['min']); $this->assertEquals(1000, $attribute['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => null, 'min' => 0, - 'max' => 1000, + 'max' => 1000 ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2223,23 +2225,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 456, 'min' => 100, - 'max' => 2000, + 'max' => 2000 ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2250,66 +2252,66 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', 'default' => 123, 'min' => 0, - 'max' => 500, + 'max' => 500 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 'i am no integer', 'min' => 0, - 'max' => 500, + 'max' => 500 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 100, 'min' => 'i am no integer', - 'max' => 500, + 'max' => 500 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 100, 'min' => 0, - 'max' => 'i am no integer', + 'max' => 'i am no integer' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 100, @@ -2319,10 +2321,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 100, @@ -2332,10 +2334,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'min' => 0, @@ -2345,10 +2347,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'default' => 50, 'min' => 0, @@ -2358,57 +2360,58 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, 'default' => 50, 'min' => 0, - 'max' => 100, + 'max' => 100 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 50, 'min' => 55, - 'max' => 100, + 'max' => 100 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 105, 'min' => 50, - 'max' => 100, + 'max' => 100 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/integer/'.$key, array_merge([ + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 50, 'min' => 200, - 'max' => 100, + 'max' => 100 ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2424,23 +2427,23 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, 'min' => 0.0, - 'max' => 1000.0, + 'max' => 1000.0 ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2448,36 +2451,36 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123.456, $attribute['default']); $this->assertEquals(0, $attribute['min']); $this->assertEquals(1000, $attribute['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => null, 'min' => 0.0, - 'max' => 1000.0, + 'max' => 1000.0 ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2485,23 +2488,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $new['body']['min']); $this->assertEquals(1000, $new['body']['max']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 456.789, 'min' => 123.456, - 'max' => 2000.0, + 'max' => 2000.0 ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2512,66 +2515,66 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', 'default' => 123.456, 'min' => 0.0, - 'max' => 1000.0, + 'max' => 1000.0 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 'i am no integer', 'min' => 0.0, - 'max' => 500.0, + 'max' => 500.0 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, 'min' => 'i am no integer', - 'max' => 500.0, + 'max' => 500.0 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, 'min' => 0.0, - 'max' => 'i am no integer', + 'max' => 'i am no integer' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, @@ -2581,10 +2584,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, @@ -2594,10 +2597,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'min' => 0.0, @@ -2607,10 +2610,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'default' => 123.456, 'min' => 0.0, @@ -2620,57 +2623,58 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, 'default' => 123.456, 'min' => 0.0, - 'max' => 100.0, + 'max' => 100.0 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, 'min' => 200.0, - 'max' => 300.0, + 'max' => 300.0 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123.456, 'min' => 0.0, - 'max' => 100.0, + 'max' => 100.0 ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/float/'.$key, array_merge([ + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 50.0, 'min' => 200.0, - 'max' => 100.0, + 'max' => 100.0 ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2686,72 +2690,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => true, + 'default' => true ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertEquals(true, $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(true, $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => false, + 'default' => false ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2760,34 +2764,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', - 'default' => true, + 'default' => true ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'i am no boolean', + 'default' => 'i am no boolean' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, ]); @@ -2795,24 +2799,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'default' => false, + 'default' => false ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/boolean/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, - 'default' => true, + 'default' => true ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2828,72 +2832,72 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => '1975-06-12 14:12:55+02:00', + 'default' => '1975-06-12 14:12:55+02:00' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertEquals('1975-06-12 14:12:55+02:00', $new['body']['default']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('1975-06-12 14:12:55+02:00', $attribute['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); $this->assertNull($new['body']['default']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => '1965-06-12 14:12:55+02:00', + 'default' => '1965-06-12 14:12:55+02:00' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2902,34 +2906,34 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', - 'default' => '1975-06-12 14:12:55+02:00', + 'default' => '1975-06-12 14:12:55+02:00' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, - 'default' => 'i am no datetime', + 'default' => 'i am no datetime' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, ]); @@ -2937,24 +2941,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'default' => '1975-06-12 14:12:55+02:00', + 'default' => '1975-06-12 14:12:55+02:00' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/datetime/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, - 'default' => '1975-06-12 14:12:55+02:00', + 'default' => '1975-06-12 14:12:55+02:00' ]); $this->assertEquals(400, $update['headers']['status-code']); @@ -2970,22 +2974,22 @@ class DatabasesCustomServerTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'elements' => ['lorem', 'ipsum', 'dolor'], 'required' => false, - 'default' => 'lorem', + 'default' => 'lorem' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -2995,13 +2999,13 @@ class DatabasesCustomServerTest extends Scope $this->assertContains('ipsum', $new['body']['elements']); $this->assertContains('dolor', $new['body']['elements']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn(array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); @@ -3010,22 +3014,22 @@ class DatabasesCustomServerTest extends Scope $this->assertContains('ipsum', $attribute['elements']); $this->assertContains('dolor', $attribute['elements']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'elements' => ['lorem', 'ipsum', 'dolor'], 'required' => false, - 'default' => null, + 'default' => null ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -3035,22 +3039,22 @@ class DatabasesCustomServerTest extends Scope $this->assertContains('ipsum', $new['body']['elements']); $this->assertContains('dolor', $new['body']['elements']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'elements' => ['ipsum', 'dolor'], 'required' => false, - 'default' => 'dolor', + 'default' => 'dolor' ]); $this->assertEquals(200, $update['headers']['status-code']); - $new = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key, array_merge([ + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertFalse($new['body']['required']); @@ -3062,36 +3066,36 @@ class DatabasesCustomServerTest extends Scope /** * Test against failure */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'elements' => [], 'required' => false, - 'default' => 'lorem', + 'default' => 'lorem' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'elements' => ['ipsum', 'dolor'], 'required' => false, - 'default' => 'lorem', + 'default' => 'lorem' ]); $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => 'no boolean', 'default' => 'lorem', @@ -3101,10 +3105,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 123, @@ -3114,10 +3118,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 'lorem', @@ -3127,10 +3131,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => false, 'default' => 'lorem', @@ -3139,10 +3143,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, 'elements' => ['lorem', 'ipsum', 'dolor'], @@ -3151,10 +3155,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'default' => 'lorem', 'elements' => ['lorem', 'ipsum', 'dolor'], @@ -3163,10 +3167,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/enum/'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'required' => true, 'default' => 'lorem', @@ -3188,51 +3192,51 @@ class DatabasesCustomServerTest extends Scope $attributes = [ 'string' => [ 'required' => false, - 'default' => 'ipsum', + 'default' => 'ipsum' ], 'email' => [ 'required' => false, - 'default' => 'eldad@appwrite.io', + 'default' => 'eldad@appwrite.io' ], 'ip' => [ 'required' => false, - 'default' => '127.0.0.1', + 'default' => '127.0.0.1' ], 'url' => [ 'required' => false, - 'default' => 'https://appwrite.io', + 'default' => 'https://appwrite.io' ], 'integer' => [ 'required' => false, 'default' => 5, 'min' => 0, - 'max' => 10, + 'max' => 10 ], 'float' => [ 'required' => false, 'default' => 5.5, 'min' => 0.0, - 'max' => 10.0, + 'max' => 10.0 ], 'datetime' => [ 'required' => false, - 'default' => '1975-06-12 14:12:55+02:00', + 'default' => '1975-06-12 14:12:55+02:00' ], 'enum' => [ 'elements' => ['lorem', 'ipsum', 'dolor'], 'required' => false, - 'default' => 'lorem', - ], + 'default' => 'lorem' + ] ]; foreach ($attributes as $key => $payload) { /** * Check if Database exists */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/i_dont_exist/collections/'.$collectionId.'/attributes/'.$key.'/unknown_'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/i_dont_exist/collections/' . $collectionId . '/attributes/' . $key . '/unknown_' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); @@ -3241,10 +3245,10 @@ class DatabasesCustomServerTest extends Scope /** * Check if Collection exists */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/i_dont_exist/attributes/'.$key.'/unknown_'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/i_dont_exist/attributes/' . $key . '/unknown_' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); @@ -3253,10 +3257,10 @@ class DatabasesCustomServerTest extends Scope /** * Check if Attribute exists */ - $update = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collectionId.'/attributes/'.$key.'/unknown_'.$key, array_merge([ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $key . '/unknown_' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php index 7f28097e70..b1d197f010 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -22,7 +22,7 @@ class DatabasesPermissionsGuestTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'InvalidDocumentDatabase', @@ -31,7 +31,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; - $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ + $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ @@ -41,7 +41,7 @@ class DatabasesPermissionsGuestTest extends Scope Permission::delete(Role::any()), ], ]); - $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ + $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [], @@ -51,12 +51,12 @@ class DatabasesPermissionsGuestTest extends Scope $publicCollection = ['id' => $publicMovies['body']['$id']]; $privateCollection = ['id' => $privateMovies['body']['$id']]; - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$publicCollection['id'].'/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollection['id'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollection['id'].'/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollection['id'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -93,14 +93,14 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents', $this->getServerHeader(), [ + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], 'permissions' => $permissions, ]); - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', $this->getServerHeader(), [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -114,11 +114,11 @@ class DatabasesPermissionsGuestTest extends Scope $roles = Authorization::getRoles(); Authorization::cleanRoles(); - $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents', [ + $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - $privateDocuments = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', [ + $privateDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -148,20 +148,20 @@ class DatabasesPermissionsGuestTest extends Scope $roles = Authorization::getRoles(); Authorization::cleanRoles(); - $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents', [ + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', - ], + ] ]); $publicDocumentId = $publicResponse['body']['$id']; $this->assertEquals(201, $publicResponse['headers']['status-code']); - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -174,7 +174,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateResponse['headers']['status-code']); // Create a document in private collection with API key so we can test that update and delete are also not allowed - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents', $this->getServerHeader(), [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -184,7 +184,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $privateResponse['headers']['status-code']); $privateDocumentId = $privateResponse['body']['$id']; - $publicDocument = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents/'.$publicDocumentId, [ + $publicDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents/' . $publicDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -196,7 +196,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(200, $publicDocument['headers']['status-code']); $this->assertEquals('Thor: Ragnarok', $publicDocument['body']['title']); - $privateDocument = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents/'.$privateDocumentId, [ + $privateDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents/' . $privateDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -207,14 +207,14 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); - $publicDocument = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$publicCollectionId.'/documents/'.$publicDocumentId, [ + $publicDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents/' . $publicDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(204, $publicDocument['headers']['status-code']); - $privateDocument = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$privateCollectionId.'/documents/'.$privateDocumentId, [ + $privateDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents/' . $privateDocumentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -231,7 +231,7 @@ class DatabasesPermissionsGuestTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'GuestPermissionsWrite', @@ -240,18 +240,18 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals('GuestPermissionsWrite', $database['body']['name']); $databaseId = $database['body']['$id']; - $movies = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::create(Role::any()), ], - 'documentSecurity' => true, + 'documentSecurity' => true ]); $moviesId = $movies['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -259,7 +259,7 @@ class DatabasesPermissionsGuestTest extends Scope sleep(1); - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$moviesId.'/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -269,7 +269,7 @@ class DatabasesPermissionsGuestTest extends Scope ], 'permissions' => [ Permission::read(Role::any()), - ], + ] ]); $this->assertEquals(201, $document['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php index 73393b7efa..860fb7fb12 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php @@ -110,7 +110,6 @@ class DatabasesPermissionsMemberTest extends Scope * Data providers lose object state so explicitly pass [$users, $collections] to each iteration * * @return array - * * @throws \Exception */ public function testSetupDatabase(): array @@ -125,7 +124,7 @@ class DatabasesPermissionsMemberTest extends Scope $databaseId = $db['body']['$id']; - $public = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ + $public = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ @@ -139,14 +138,14 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $public['headers']['status-code']); $this->collections = ['public' => $public['body']['$id']]; - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$this->collections['public'].'/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['public'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); $this->assertEquals(202, $response['headers']['status-code']); - $private = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ + $private = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Private Movies', 'permissions' => [ @@ -160,14 +159,14 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $private['headers']['status-code']); $this->collections['private'] = $private['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$this->collections['private'].'/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['private'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); $this->assertEquals(202, $response['headers']['status-code']); - $doconly = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', $this->getServerHeader(), [ + $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::unique(), 'name' => 'Document Only Movies', 'permissions' => [], @@ -176,7 +175,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $private['headers']['status-code']); $this->collections['doconly'] = $doconly['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$this->collections['doconly'].'/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['doconly'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -188,13 +187,12 @@ class DatabasesPermissionsMemberTest extends Scope return [ 'users' => $this->users, 'collections' => $this->collections, - 'databaseId' => $databaseId, + 'databaseId' => $databaseId ]; } /** * Data provider params are passed before test dependencies - * * @dataProvider permissionsProvider * @depends testSetupDatabase */ @@ -204,41 +202,41 @@ class DatabasesPermissionsMemberTest extends Scope $collections = $data['collections']; $databaseId = $data['databaseId']; - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collections['public'].'/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], - 'permissions' => $permissions, + 'permissions' => $permissions ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collections['private'].'/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], - 'permissions' => $permissions, + 'permissions' => $permissions ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collections['doconly'].'/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], - 'permissions' => $permissions, + 'permissions' => $permissions ]); $this->assertEquals(201, $response['headers']['status-code']); /** * Check "any" permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collections['public'].'/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users['user1']['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -247,11 +245,11 @@ class DatabasesPermissionsMemberTest extends Scope /** * Check "users" permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collections['private'].'/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users['user1']['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -260,11 +258,11 @@ class DatabasesPermissionsMemberTest extends Scope /** * Check "user:user1" document only permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collections['doconly'].'/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users['user1']['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], ]); $this->assertEquals(200, $documents['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php b/tests/e2e/Services/Databases/DatabasesPermissionsScope.php index a78153cf7d..181231adc5 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsScope.php @@ -7,7 +7,6 @@ use Tests\E2E\Client; trait DatabasesPermissionsScope { public array $users = []; - public array $teams = []; public function createUser(string $id, string $email, string $password = 'test123!'): array @@ -19,7 +18,7 @@ trait DatabasesPermissionsScope ], [ 'userId' => $id, 'email' => $email, - 'password' => $password, + 'password' => $password ]); $this->assertEquals(201, $user['headers']['status-code']); @@ -33,7 +32,7 @@ trait DatabasesPermissionsScope 'password' => $password, ]); - $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $user = [ '$id' => $user['body']['$id'], @@ -54,7 +53,7 @@ trait DatabasesPermissionsScope { $team = $this->client->call(Client::METHOD_POST, '/teams', $this->getServerHeader(), [ 'teamId' => $id, - 'name' => $name, + 'name' => $name ]); $this->teams[$id] = $team['body']; @@ -63,16 +62,16 @@ trait DatabasesPermissionsScope public function addToTeam(string $user, string $team, array $roles = []): array { - $membership = $this->client->call(Client::METHOD_POST, '/teams/'.$team.'/memberships', $this->getServerHeader(), [ + $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team . '/memberships', $this->getServerHeader(), [ 'teamId' => $team, 'email' => $this->getCreatedUser($user)['email'], 'roles' => $roles, - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); return [ 'user' => $membership['body']['userId'], - 'membership' => $membership['body']['$id'], + 'membership' => $membership['body']['$id'] ]; } @@ -81,7 +80,7 @@ trait DatabasesPermissionsScope return [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]; } } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php index e592902ab8..dcbf3e4bff 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -17,7 +17,6 @@ class DatabasesPermissionsTeamTest extends Scope use DatabasesPermissionsScope; public array $collections = []; - public string $databaseId = 'testpermissiondb'; public function createTeams(): array @@ -45,7 +44,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $this->assertEquals(201, $db['headers']['status-code']); - $collection1 = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections', $this->getServerHeader(), [ + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::custom('collection1'), 'name' => 'Collection 1', 'permissions' => [ @@ -58,13 +57,13 @@ class DatabasesPermissionsTeamTest extends Scope $this->collections['collection1'] = $collection1['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection1'].'/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection1'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections', $this->getServerHeader(), [ + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ 'collectionId' => ID::custom('collection2'), 'name' => 'Collection 2', 'permissions' => [ @@ -72,12 +71,12 @@ class DatabasesPermissionsTeamTest extends Scope Permission::create(Role::team($teams['team2']['$id'], 'owner')), Permission::update(Role::team($teams['team2']['$id'], 'owner')), Permission::delete(Role::team($teams['team2']['$id'], 'owner')), - ], + ] ]); $this->collections['collection2'] = $collection2['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection2'].'/attributes/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection2'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -125,7 +124,6 @@ class DatabasesPermissionsTeamTest extends Scope * * Data providers lose object state * so explicitly pass $users to each iteration - * * @return array $users */ public function testSetupDatabase(): array @@ -142,7 +140,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->createCollections($this->teams); - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection1'].'/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection1'] . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -150,7 +148,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$this->collections['collection2'].'/documents', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection2'] . '/documents', $this->getServerHeader(), [ 'documentId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', @@ -163,17 +161,16 @@ class DatabasesPermissionsTeamTest extends Scope /** * Data provider params are passed before test dependencies - * * @depends testSetupDatabase * @dataProvider readDocumentsProvider */ public function testReadDocuments($user, $collection, $success, $users) { - $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$this->databaseId.'/collections/'.$collection.'/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $this->databaseId . '/collections/' . $collection . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users[$user]['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], ]); if ($success) { @@ -189,11 +186,11 @@ class DatabasesPermissionsTeamTest extends Scope */ public function testWriteDocuments($user, $collection, $success, $users) { - $documents = $this->client->call(Client::METHOD_POST, '/databases/'.$this->databaseId.'/collections/'.$collection.'/documents', [ + $documents = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $collection . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$users[$user]['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], ], [ 'documentId' => ID::unique(), 'data' => [ diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index ad41ab7e47..c45ebbe068 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -8,12 +8,11 @@ use Utopia\CLI\Console; trait FunctionsBase { protected string $stdout = ''; - protected string $stderr = ''; protected function packageCode($folder) { - Console::execute('cd '.realpath(__DIR__.'/../../../resources/functions')."/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr); + Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr); } // /** diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index fec65fd3b9..e28bdd233f 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -2,9 +2,9 @@ namespace Tests\E2E\Services\Functions; -use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Client; use Tests\E2E\Scopes\SideConsole; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -41,13 +41,13 @@ class FunctionsConsoleClientTest extends Scope 'functionId' => ID::unique(), 'name' => 'Test Failure', 'execute' => ['some-random-string'], - 'runtime' => 'php-8.0', + 'runtime' => 'php-8.0' ]); $this->assertEquals(400, $response['headers']['status-code']); return [ - 'functionId' => $function['body']['$id'], + 'functionId' => $function['body']['$id'] ]; } @@ -59,20 +59,21 @@ class FunctionsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/usage', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '232h', + 'range' => '232h' ]); $this->assertEquals(400, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_GET, '/functions/randomFunctionId/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -80,11 +81,12 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/usage', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -107,12 +109,13 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ + + $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST', - 'value' => 'TESTINGVALUE', + 'value' => 'TESTINGVALUE' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -121,12 +124,13 @@ class FunctionsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ + + $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST', - 'value' => 'ANOTHER_TESTINGVALUE', + 'value' => 'ANOTHER_TESTINGVALUE' ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -134,28 +138,28 @@ class FunctionsConsoleClientTest extends Scope return array_merge( $data, [ - 'variableId' => $variableId, + 'variableId' => $variableId ] ); - $longKey = str_repeat('A', 256); - $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ + $longKey = str_repeat("A", 256); + $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => $longKey, - 'value' => 'TESTINGVALUE', + 'value' => 'TESTINGVALUE' ]); $this->assertEquals(400, $response['headers']['status-code']); - $longValue = str_repeat('#', 8193); - $response = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ + $longValue = str_repeat("#", 8193); + $response = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'LONGKEY', - 'value' => $longValue, + 'value' => $longValue ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -169,16 +173,17 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, count($response['body']['variables'])); + $this->assertEquals(1, sizeof($response['body']['variables'])); $this->assertEquals(1, $response['body']['total']); - $this->assertEquals('APP_TEST', $response['body']['variables'][0]['key']); - $this->assertEquals('TESTINGVALUE', $response['body']['variables'][0]['value']); + $this->assertEquals("APP_TEST", $response['body']['variables'][0]['key']); + $this->assertEquals("TESTINGVALUE", $response['body']['variables'][0]['value']); /** * Test for FAILURE @@ -195,19 +200,21 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals('APP_TEST', $response['body']['key']); - $this->assertEquals('TESTINGVALUE', $response['body']['value']); + $this->assertEquals("APP_TEST", $response['body']['key']); + $this->assertEquals("TESTINGVALUE", $response['body']['value']); /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/NON_EXISTING_VARIABLE', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/NON_EXISTING_VARIABLE', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -225,28 +232,29 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST_UPDATE', - 'value' => 'TESTINGVALUEUPDATED', + 'value' => 'TESTINGVALUEUPDATED' ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals('APP_TEST_UPDATE', $response['body']['key']); - $this->assertEquals('TESTINGVALUEUPDATED', $response['body']['value']); + $this->assertEquals("APP_TEST_UPDATE", $response['body']['key']); + $this->assertEquals("TESTINGVALUEUPDATED", $response['body']['value']); - $variable = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + $variable = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $variable['headers']['status-code']); - $this->assertEquals('APP_TEST_UPDATE', $variable['body']['key']); - $this->assertEquals('TESTINGVALUEUPDATED', $variable['body']['value']); + $this->assertEquals("APP_TEST_UPDATE", $variable['body']['key']); + $this->assertEquals("TESTINGVALUEUPDATED", $variable['body']['value']); - $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -254,55 +262,56 @@ class FunctionsConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals('APP_TEST_UPDATE_2', $response['body']['key']); - $this->assertEquals('TESTINGVALUEUPDATED', $response['body']['value']); + $this->assertEquals("APP_TEST_UPDATE_2", $response['body']['key']); + $this->assertEquals("TESTINGVALUEUPDATED", $response['body']['value']); - $variable = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + $variable = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $variable['headers']['status-code']); - $this->assertEquals('APP_TEST_UPDATE_2', $variable['body']['key']); - $this->assertEquals('TESTINGVALUEUPDATED', $variable['body']['value']); + $this->assertEquals("APP_TEST_UPDATE_2", $variable['body']['key']); + $this->assertEquals("TESTINGVALUEUPDATED", $variable['body']['value']); /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'value' => 'TESTINGVALUEUPDATED_2', + 'value' => 'TESTINGVALUEUPDATED_2' ]); $this->assertEquals(400, $response['headers']['status-code']); - $longKey = str_repeat('A', 256); - $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + $longKey = str_repeat("A", 256); + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => $longKey, - 'value' => 'TESTINGVALUEUPDATED', + 'value' => 'TESTINGVALUEUPDATED' ]); $this->assertEquals(400, $response['headers']['status-code']); - $longValue = str_repeat('#', 8193); - $response = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + $longValue = str_repeat("#", 8193); + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'APP_TEST_UPDATE', - 'value' => $longValue, + 'value' => $longValue ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -318,26 +327,28 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/variables/'.$data['variableId'], array_merge([ + + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/variables', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(0, count($response['body']['variables'])); + $this->assertEquals(0, sizeof($response['body']['variables'])); $this->assertEquals(0, $response['body']['total']); /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/variables/NON_EXISTING_VARIABLE', array_merge([ + + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/variables/NON_EXISTING_VARIABLE', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index b92308d348..713814e17f 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -65,7 +65,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/variables', [ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -74,7 +74,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/variables', [ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -83,7 +83,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/variables', [ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -97,17 +97,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $variable3['headers']['status-code']); $folder = 'php'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -117,7 +117,7 @@ class FunctionsCustomClientTest extends Scope // Wait for deployment to be built. sleep(20); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$function['body']['$id'].'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $function['body']['$id'] . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -125,7 +125,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -134,7 +134,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(401, $execution['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -144,7 +144,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $execution['headers']['status-code']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$function['body']['$id'], [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $function['body']['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -180,7 +180,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -189,7 +189,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -198,7 +198,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -212,17 +212,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $variable3['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -232,7 +232,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -240,12 +240,12 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true, + 'async' => true ]); $this->assertEquals(202, $execution['headers']['status-code']); @@ -254,7 +254,7 @@ class FunctionsCustomClientTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -277,7 +277,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals($projectId, $output['APPWRITE_FUNCTION_PROJECT_ID']); return [ - 'functionId' => $functionId, + 'functionId' => $functionId ]; } @@ -311,17 +311,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -332,7 +332,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); // Why do we have to do this? - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -340,7 +340,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], [ @@ -365,7 +365,7 @@ class FunctionsCustomClientTest extends Scope 'timeout' => 10, ]); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -386,19 +386,19 @@ class FunctionsCustomClientTest extends Scope $projectId = $this->getProject()['$id']; $apikey = $this->getProject()['apiKey']; - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true, + 'async' => true ]); $this->assertEquals(202, $execution['headers']['status-code']); sleep(20); - $base = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $base = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -409,71 +409,71 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('completed', $base['body']['executions'][0]['status']); $this->assertEquals('completed', $base['body']['executions'][1]['status']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(1, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(1, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => ['equal("status", ["completed"])'], + 'queries' => [ 'equal("status", ["completed"])' ] ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(2, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => ['equal("status", ["failed"])'], + 'queries' => [ 'equal("status", ["failed"])' ] ]); $this->assertEquals(200, $executions['headers']['status-code']); $this->assertCount(0, $executions['body']['executions']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => ['cursorAfter("'.$base['body']['executions'][0]['$id'].'")'], + 'queries' => [ 'cursorAfter("' . $base['body']['executions'][0]['$id'] . '")' ], ]); $this->assertCount(1, $executions['body']['executions']); $this->assertEquals($base['body']['executions'][1]['$id'], $executions['body']['executions'][0]['$id']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'queries' => ['cursorBefore("'.$base['body']['executions'][1]['$id'].'")'], + 'queries' => [ 'cursorBefore("' . $base['body']['executions'][1]['$id'] . '")' ], ]); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -487,6 +487,7 @@ class FunctionsCustomClientTest extends Scope /** * Test for SUCCESS */ + $projectId = $this->getProject()['$id']; $apikey = $this->getProject()['apiKey']; @@ -507,7 +508,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -516,7 +517,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -525,7 +526,7 @@ class FunctionsCustomClientTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', [ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -539,17 +540,17 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $variable3['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -559,7 +560,7 @@ class FunctionsCustomClientTest extends Scope // Wait for deployment to be built. sleep(20); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -567,7 +568,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ @@ -595,7 +596,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEmpty($execution['body']['stderr']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 6ad1e578cb..ab931f14e4 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -55,7 +56,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(10, $response1['body']['timeout']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -63,7 +64,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -71,7 +72,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -108,7 +109,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => $data['functionId'], + 'search' => $data['functionId'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -119,7 +120,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -129,7 +130,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -139,7 +140,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("enabled", true)'], + 'queries' => [ 'equal("enabled", true)' ] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -149,7 +150,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("enabled", false)'], + 'queries' => [ 'equal("enabled", false)' ] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -159,7 +160,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Test', + 'search' => 'Test' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -170,7 +171,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'php-8.0', + 'search' => 'php-8.0' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -197,7 +198,7 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($response['body']['$id']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$response['body']['$id'].'/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $response['body']['$id'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -205,7 +206,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue1', ]); - $variable2 = $this->client->call(Client::METHOD_POST, '/functions/'.$response['body']['$id'].'/variables', array_merge([ + $variable2 = $this->client->call(Client::METHOD_POST, '/functions/' . $response['body']['$id'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -213,7 +214,7 @@ class FunctionsCustomServerTest extends Scope 'value' => 'funcValue2', ]); - $variable3 = $this->client->call(Client::METHOD_POST, '/functions/'.$response['body']['$id'].'/variables', array_merge([ + $variable3 = $this->client->call(Client::METHOD_POST, '/functions/' . $response['body']['$id'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -241,7 +242,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$functions['body']['functions'][0]['$id'].'")'], + 'queries' => [ 'cursorAfter("' . $functions['body']['functions'][0]['$id'] . '")' ], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -252,7 +253,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$functions['body']['functions'][1]['$id'].'")'], + 'queries' => [ 'cursorBefore("' . $functions['body']['functions'][1]['$id'] . '")' ], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -266,7 +267,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("unknown")'], + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -282,7 +283,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -311,7 +312,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $response1 = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'], array_merge([ + $response1 = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -354,16 +355,16 @@ class FunctionsCustomServerTest extends Scope * Test for SUCCESS */ $folder = 'php'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -387,30 +388,31 @@ class FunctionsCustomServerTest extends Scope /** * Test for Large Code File SUCCESS */ + $folder = 'php-large'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); $chunkSize = 5 * 1024 * 1024; - $handle = @fopen($code, 'rb'); + $handle = @fopen($code, "rb"); $mimeType = 'application/x-gzip'; $counter = 0; $size = filesize($code); $headers = [ 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ]; $id = ''; - while (! feof($handle)) { - $curlFile = new \CURLFile('data://'.$mimeType.';base64,'.base64_encode(@fread($handle, $chunkSize)), $mimeType, 'php-large-fx.tar.gz'); - $headers['content-range'] = 'bytes '.($counter * $chunkSize).'-'.min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1).'/'.$size; - if (! empty($id)) { + while (!feof($handle)) { + $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'php-large-fx.tar.gz'); + $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; + if (!empty($id)) { $headers['x-appwrite-id'] = $id; } - $largeTag = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge($headers, $this->getHeaders()), [ + $largeTag = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge($headers, $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => $curlFile, - 'activate' => true, + 'activate' => true ]); $counter++; $id = $largeTag['body']['$id']; @@ -434,7 +436,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -461,7 +463,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -474,11 +476,11 @@ class FunctionsCustomServerTest extends Scope /** * Test search queries */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => $data['functionId'], + 'search' => $data['functionId'] ])); $this->assertEquals($function['headers']['status-code'], 200); @@ -487,51 +489,51 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(2, $function['body']['deployments']); $this->assertEquals($function['body']['deployments'][0]['$id'], $data['deploymentId']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(1, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(1, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("entrypoint", "index.php")'], + 'queries' => [ 'equal("entrypoint", "index.php")' ] ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(2, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("entrypoint", "index.js")'], + 'queries' => [ 'equal("entrypoint", "index.js")' ] ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertCount(0, $function['body']['deployments']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => 'Test', + 'search' => 'Test' ])); $this->assertEquals($function['headers']['status-code'], 200); @@ -540,11 +542,11 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(2, $function['body']['deployments']); $this->assertEquals($function['body']['deployments'][0]['$id'], $data['deploymentId']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => 'php-8.0', + 'search' => 'php-8.0' ])); $this->assertEquals($function['headers']['status-code'], 200); @@ -564,7 +566,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -578,7 +580,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for FAILURE */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments/x', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments/x', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -596,7 +598,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -618,7 +620,7 @@ class FunctionsCustomServerTest extends Scope sleep(10); - $execution = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/'.$executionId, array_merge([ + $execution = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions/' . $executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -642,6 +644,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for FAILURE */ + sleep(20); return array_merge($data, ['executionId' => $executionId]); @@ -655,7 +658,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -666,31 +669,31 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $function['body']['executions']); $this->assertEquals($function['body']['executions'][0]['$id'], $data['executionId']); - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(1, $response['body']['executions']); - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(0, $response['body']['executions']); - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("trigger", "http")'], + 'queries' => [ 'equal("trigger", "http")' ] ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -699,7 +702,8 @@ class FunctionsCustomServerTest extends Scope /** * Test search queries */ - $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + + $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()), [ @@ -712,7 +716,7 @@ class FunctionsCustomServerTest extends Scope $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([ + $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()), [ @@ -737,7 +741,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -765,7 +769,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/'.$data['executionId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions/' . $data['executionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -776,7 +780,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for FAILURE */ - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/x', array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions/x', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -794,7 +798,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ + $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -802,7 +806,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $function['headers']['status-code']); $this->assertEmpty($function['body']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/deployments/'.$data['deploymentId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments/' . $data['deploymentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -824,7 +828,7 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -832,7 +836,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $function['headers']['status-code']); $this->assertEmpty($function['body']); - $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -852,7 +856,7 @@ class FunctionsCustomServerTest extends Scope $entrypoint = 'index.php'; $timeout = 2; $folder = 'timeout'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ @@ -860,7 +864,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test '.$name, + 'name' => 'Test ' . $name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -870,7 +874,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -884,7 +888,7 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(40); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -897,7 +901,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -916,7 +920,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['stderr'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -934,7 +938,7 @@ class FunctionsCustomServerTest extends Scope $entrypoint = 'index.php'; $timeout = 2; $folder = 'php-fn'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ @@ -942,7 +946,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test '.$name, + 'name' => 'Test ' . $name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -952,13 +956,13 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => $entrypoint, 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -967,19 +971,19 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(20); - $deployment = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, array_merge([ + $deployment = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); $this->assertEquals(200, $deployment['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true, + 'async' => true ]); $executionId = $execution['body']['$id'] ?? ''; @@ -990,7 +994,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1000,7 +1004,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1013,7 +1017,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); $this->assertStringContainsString('Amazing Function Log', $executions['body']['stdout']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1027,7 +1031,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1036,11 +1040,12 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } + public function testCreateCustomNodeExecution() { $name = 'node-18.0'; $folder = 'node'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); $entrypoint = 'index.js'; @@ -1051,7 +1056,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test '.$name, + 'name' => 'Test ' . $name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -1062,7 +1067,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); // Create variable - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1072,7 +1077,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1087,12 +1092,12 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(20); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true, + 'async' => true ]); $executionId = $execution['body']['$id'] ?? ''; @@ -1103,7 +1108,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1113,7 +1118,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('Node.js', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1125,7 +1130,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1139,7 +1144,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1152,7 +1157,7 @@ class FunctionsCustomServerTest extends Scope { $name = 'python-3.9'; $folder = 'python'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); $entrypoint = 'main.py'; @@ -1163,7 +1168,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test '.$name, + 'name' => 'Test ' . $name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -1174,7 +1179,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1184,7 +1189,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1199,12 +1204,12 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(60); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true, + 'async' => true ]); $executionId = $execution['body']['$id'] ?? ''; @@ -1215,7 +1220,7 @@ class FunctionsCustomServerTest extends Scope sleep(60); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1225,7 +1230,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('Python', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1238,7 +1243,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1252,7 +1257,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1378,7 +1383,7 @@ class FunctionsCustomServerTest extends Scope { $name = 'ruby-3.1'; $folder = 'ruby'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); $entrypoint = 'main.rb'; @@ -1389,7 +1394,7 @@ class FunctionsCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'functionId' => ID::unique(), - 'name' => 'Test '.$name, + 'name' => 'Test ' . $name, 'runtime' => $name, 'events' => [], 'timeout' => $timeout, @@ -1400,7 +1405,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); /** Create Variables */ - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1410,7 +1415,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1425,12 +1430,12 @@ class FunctionsCustomServerTest extends Scope // Allow build step to run sleep(60); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => 'foobar', - 'async' => true, + 'async' => true ]); $executionId = $execution['body']['$id'] ?? ''; @@ -1441,7 +1446,7 @@ class FunctionsCustomServerTest extends Scope sleep(20); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1451,7 +1456,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $executions['headers']['status-code']); $this->assertEquals('completed', $executions['body']['status']); $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); - $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals('Test ' . $name, $output['APPWRITE_FUNCTION_NAME']); $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); $this->assertEquals('Ruby', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); @@ -1463,7 +1468,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1477,7 +1482,7 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/AbuseTest.php index 163f695811..48ee64d141 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/AbuseTest.php @@ -92,7 +92,7 @@ class AbuseTest extends Scope $max = App::getEnv('_APP_GRAPHQL_MAX_QUERY_COMPLEXITY', 250); - $this->assertEquals('Max query complexity should be '.$max.' but got 259.', $response['body']['errors'][0]['message']); + $this->assertEquals('Max query complexity should be ' . $max . ' but got 259.', $response['body']['errors'][0]['message']); } public function testTooManyQueriesBlocked() @@ -122,7 +122,7 @@ class AbuseTest extends Scope 'variables' => [ 'databaseId' => 'actors', 'name' => 'AbuseDatabase', - ], + ] ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -145,7 +145,7 @@ class AbuseTest extends Scope Permission::read(Role::any()), Permission::write(Role::any()), ], - ], + ] ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -165,7 +165,7 @@ class AbuseTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ], + ] ]; $this->client->call(Client::METHOD_POST, '/graphql', [ diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index c77773cba9..7fd70b5015 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -18,7 +18,7 @@ class AccountTest extends Scope { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_ACCOUNT); - $email = 'test'.\rand().'@test.com'; + $email = 'test' . \rand() . '@test.com'; $graphQLPayload = [ 'query' => $query, 'variables' => [ @@ -51,7 +51,7 @@ class AccountTest extends Scope 'variables' => [ 'email' => $this->getUser()['email'], 'password' => 'password', - ], + ] ]; $session = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -63,7 +63,7 @@ class AccountTest extends Scope $this->assertIsArray($session['body']['data']); $this->assertIsArray($session['body']['data']['accountCreateEmailSession']); - $cookie = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $cookie = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertNotEmpty($cookie); } @@ -71,13 +71,13 @@ class AccountTest extends Scope { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_MAGIC_URL); - $email = 'test'.\rand().'@test.com'; + $email = 'test' . \rand() . '@test.com'; $graphQLPayload = [ 'query' => $query, 'variables' => [ 'userId' => ID::unique(), 'email' => $email, - ], + ] ]; $session = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -99,7 +99,7 @@ class AccountTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'url' => 'http://localhost/verification', + 'url' => 'http://localhost/verification' ], ]; @@ -117,9 +117,7 @@ class AccountTest extends Scope /** * @depends testUpdateAccountPhone - * * @return array - * * @throws \Exception */ public function testCreatePhoneVerification(): array @@ -276,7 +274,7 @@ class AccountTest extends Scope 'query' => $query, 'variables' => [ 'sessionId' => 'current', - ], + ] ]; $session = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -319,8 +317,8 @@ class AccountTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'name' => 'Tester Updated', - ], + 'name' => 'Tester Updated' + ] ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -345,7 +343,7 @@ class AccountTest extends Scope 'variables' => [ 'email' => 'newemail@appwrite.io', 'password' => 'password', - ], + ] ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -370,7 +368,7 @@ class AccountTest extends Scope 'variables' => [ 'oldPassword' => 'password', 'password' => 'password', - ], + ] ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -394,7 +392,7 @@ class AccountTest extends Scope 'variables' => [ 'phone' => '+123456789', 'password' => 'password', - ], + ] ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -442,9 +440,9 @@ class AccountTest extends Scope 'query' => $query, 'variables' => [ 'prefs' => [ - 'key' => 'value', - ], - ], + 'key' => 'value' + ] + ] ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -465,7 +463,7 @@ class AccountTest extends Scope $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$DELETE_ACCOUNT_SESSIONS); $graphQLPayload = [ - 'query' => $query, + 'query' => $query ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -490,7 +488,7 @@ class AccountTest extends Scope 'query' => $query, 'variables' => [ 'sessionId' => 'current', - ], + ] ]; $account = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/AuthTest.php index 63177ee3bc..c331fb8437 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/AuthTest.php @@ -7,8 +7,8 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Helpers\Permission; class AuthTest extends Scope { @@ -17,15 +17,12 @@ class AuthTest extends Scope use Base; private array $account1; - private array $account2; private string $token1; - private string $token2; private array $database; - private array $collection; public function setUp(): void @@ -35,8 +32,8 @@ class AuthTest extends Scope $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_ACCOUNT); - $email1 = 'test'.\rand().'@test.com'; - $email2 = 'test'.\rand().'@test.com'; + $email1 = 'test' . \rand() . '@test.com'; + $email2 = 'test' . \rand() . '@test.com'; // Create account 1 $graphQLPayload = [ @@ -69,7 +66,7 @@ class AuthTest extends Scope 'variables' => [ 'email' => $email1, 'password' => 'password', - ], + ] ]; $session1 = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -77,8 +74,8 @@ class AuthTest extends Scope ], $graphQLPayload); $this->token1 = $this->client->parseCookie( - (string) $session1['headers']['set-cookie'] - )['a_session_'.$projectId]; + (string)$session1['headers']['set-cookie'] + )['a_session_' . $projectId]; // Create session 2 $graphQLPayload['variables']['email'] = $email2; @@ -89,8 +86,8 @@ class AuthTest extends Scope ], $graphQLPayload); $this->token2 = $this->client->parseCookie( - (string) $session2['headers']['set-cookie'] - )['a_session_'.$projectId]; + (string)$session2['headers']['set-cookie'] + )['a_session_' . $projectId]; // Create database $query = $this->getQuery(self::$CREATE_DATABASE); @@ -99,7 +96,7 @@ class AuthTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ], + ] ]; $this->database = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -118,9 +115,9 @@ class AuthTest extends Scope 'name' => 'Actors', 'documentSecurity' => true, 'permissions' => [ - Permission::create(Role::user($userId)), - ], - ], + Permission::create(Role::user($userId)) + ] + ] ]; $this->collection = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -138,7 +135,7 @@ class AuthTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ], + ] ]; $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', @@ -169,13 +166,13 @@ class AuthTest extends Scope Permission::read(Role::user($userId)), Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), - ], - ], + ] + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$this->token1, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); // Try to read as account 1 @@ -186,12 +183,12 @@ class AuthTest extends Scope 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$this->token1, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); $this->assertIsArray($document['body']['data']['databasesGetDocument']); @@ -201,7 +198,7 @@ class AuthTest extends Scope $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$this->token2, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token2, ], $gqlPayload); $this->assertArrayHasKey('errors', $document['body']); @@ -229,12 +226,12 @@ class AuthTest extends Scope Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), ], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$this->token1, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); // Try to delete as account 1 @@ -245,12 +242,12 @@ class AuthTest extends Scope 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$this->token1, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); $this->assertIsNotArray($document['body']); diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 8f16222f1e..67d09bb4ac 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -6,342 +6,195 @@ trait Base { // Databases public static string $CREATE_DATABASE = 'create_database'; - public static string $GET_DATABASES = 'get_databases'; - public static string $GET_DATABASE = 'get_database'; - public static string $UPDATE_DATABASE = 'update_database'; - public static string $DELETE_DATABASE = 'delete_database'; - // Collections public static string $CREATE_COLLECTION = 'create_collection'; - public static string $GET_COLLECTION = 'get_collection'; - public static string $GET_COLLECTIONS = 'list_collections'; - public static string $UPDATE_COLLECTION = 'update_collection'; - public static string $DELETE_COLLECTION = 'delete_collection'; - // Attributes public static string $CREATE_STRING_ATTRIBUTE = 'create_string_attribute'; - public static string $CREATE_INTEGER_ATTRIBUTE = 'create_integer_attribute'; - public static string $CREATE_FLOAT_ATTRIBUTE = 'create_float_attribute'; - public static string $CREATE_BOOLEAN_ATTRIBUTE = 'create_boolean_attribute'; - public static string $CREATE_URL_ATTRIBUTE = 'create_url_attribute'; - public static string $CREATE_EMAIL_ATTRIBUTE = 'create_email_attribute'; - public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute'; - public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute'; - public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute'; public static string $CREATE_RELATIONSHIP_ATTRIBUTE = 'create_relationship_attribute'; - public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute'; - public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute'; - public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute'; - public static string $UPDATE_BOOLEAN_ATTRIBUTE = 'update_boolean_attribute'; - public static string $UPDATE_URL_ATTRIBUTE = 'update_url_attribute'; - public static string $UPDATE_EMAIL_ATTRIBUTE = 'update_email_attribute'; - public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute'; - public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute'; - public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute'; public static string $UPDATE_RELATIONSHIP_ATTRIBUTE = 'update_relationship_attribute'; - public static string $GET_ATTRIBUTES = 'get_attributes'; - public static string $GET_ATTRIBUTE = 'get_attribute'; - public static string $DELETE_ATTRIBUTE = 'delete_attribute'; - // Indexes public static string $CREATE_INDEX = 'create_index'; - public static string $GET_INDEXES = 'get_indexes'; - public static string $GET_INDEX = 'get_index'; - public static string $DELETE_INDEX = 'delete_index'; - // Documents public static string $CREATE_DOCUMENT = 'create_document_rest'; - public static string $GET_DOCUMENTS = 'list_documents'; - public static string $GET_DOCUMENT = 'get_document'; - public static string $UPDATE_DOCUMENT = 'update_document'; - public static string $DELETE_DOCUMENT = 'delete_document'; // Custom Entities public static string $CREATE_CUSTOM_ENTITY = 'create_custom_entity'; - public static string $GET_CUSTOM_ENTITIES = 'get_custom_entities'; - public static string $GET_CUSTOM_ENTITY = 'get_custom_entity'; - public static string $UPDATE_CUSTOM_ENTITY = 'update_custom_entity'; - public static string $DELETE_CUSTOM_ENTITY = 'delete_custom_entity'; // Account public static string $CREATE_ACCOUNT = 'create_account'; - public static string $CREATE_ACCOUNT_SESSION = 'create_account_session'; - public static string $CREATE_ANONYMOUS_SESSION = 'create_anonymous_session'; - public static string $CREATE_ACCOUNT_JWT = 'create_account_jwt'; - public static string $CREATE_MAGIC_URL = 'create_magic_url'; - public static string $CREATE_PASSWORD_RECOVERY = 'create_password_recovery'; - public static string $CREATE_EMAIL_VERIFICATION = 'create_email_verification'; - public static string $CREATE_PHONE_VERIFICATION = 'create_phone_verification'; - public static string $GET_ACCOUNT = 'get_account'; - public static string $GET_ACCOUNT_SESSION = 'get_account_session'; - public static string $GET_ACCOUNT_SESSIONS = 'get_account_sessions'; - public static string $GET_ACCOUNT_PREFS = 'get_account_preferences'; - public static string $GET_ACCOUNT_LOGS = 'get_account_logs'; - public static string $UPDATE_ACCOUNT_NAME = 'update_account_name'; - public static string $UPDATE_ACCOUNT_EMAIL = 'update_account_email'; - public static string $UPDATE_ACCOUNT_PASSWORD = 'update_account_password'; - public static string $UPDATE_ACCOUNT_PREFS = 'update_account_prefs'; - public static string $UPDATE_ACCOUNT_PHONE = 'update_account_phone'; - public static string $UPDATE_ACCOUNT_STATUS = 'update_account_status'; - public static string $UPDATE_MAGIC_URL = 'confirm_magic_url'; - public static string $UPDATE_PASSWORD_RECOVERY = 'confirm_password_recovery'; - public static string $UPDATE_EMAIL_VERIFICATION = 'confirm_email_verification'; - public static string $UPDATE_PHONE_VERIFICATION = 'confirm_phone_verification'; - public static string $DELETE_ACCOUNT_SESSION = 'delete_account_session'; - public static string $DELETE_ACCOUNT_SESSIONS = 'delete_account_sessions'; // Users public static string $CREATE_USER = 'create_user'; - public static string $GET_USER = 'get_user'; - public static string $GET_USERS = 'list_user'; - public static string $GET_USER_PREFERENCES = 'get_user_preferences'; - public static string $GET_USER_SESSIONS = 'get_user_sessions'; - public static string $GET_USER_MEMBERSHIPS = 'get_user_memberships'; - public static string $GET_USER_LOGS = 'get_user_logs'; - public static string $UPDATE_USER_STATUS = 'update_user_status'; - public static string $UPDATE_USER_NAME = 'update_user_name'; - public static string $UPDATE_USER_EMAIL = 'update_user_email'; - public static string $UPDATE_USER_EMAIL_VERIFICATION = 'update_email_verification'; - public static string $UPDATE_USER_PHONE_VERIFICATION = 'update_phone_verification'; - public static string $UPDATE_USER_PASSWORD = 'update_user_password'; - public static string $UPDATE_USER_PHONE = 'update_user_phone'; - public static string $UPDATE_USER_PREFS = 'update_user_prefs'; - public static string $DELETE_USER_SESSIONS = 'delete_user_sessions'; - public static string $DELETE_USER_SESSION = 'delete_user_session'; - public static string $DELETE_USER = 'delete_user'; // Teams public static string $GET_TEAM = 'get_team'; - public static string $GET_TEAM_PREFERENCES = 'get_team_preferences'; - public static string $GET_TEAMS = 'list_teams'; - public static string $CREATE_TEAM = 'create_team'; - public static string $UPDATE_TEAM_NAME = 'update_team_name'; - public static string $UPDATE_TEAM_PREFERENCES = 'update_team_preferences'; public static string $DELETE_TEAM = 'delete_team'; - public static string $GET_TEAM_MEMBERSHIP = 'get_team_membership'; - public static string $GET_TEAM_MEMBERSHIPS = 'list_team_memberships'; - public static string $CREATE_TEAM_MEMBERSHIP = 'create_team_membership'; - public static string $UPDATE_TEAM_MEMBERSHIP = 'update_team_membership'; - public static string $UPDATE_TEAM_MEMBERSHIP_STATUS = 'update_membership_status'; - public static string $DELETE_TEAM_MEMBERSHIP = 'delete_team_membership'; // Functions public static string $CREATE_FUNCTION = 'create_function'; - public static string $GET_FUNCTIONS = 'list_functions'; - public static string $GET_FUNCTION = 'get_function'; - public static string $GET_RUNTIMES = 'list_runtimes'; - public static string $UPDATE_FUNCTION = 'update_function'; - public static string $DELETE_FUNCTION = 'delete_function'; - // Variables public static string $CREATE_VARIABLE = 'create_variable'; - public static string $GET_VARIABLES = 'list_variables'; - public static string $GET_VARIABLE = 'get_variable'; - public static string $UPDATE_VARIABLE = 'update_variable'; - public static string $DELETE_VARIABLE = 'delete_variable'; //Deployments public static string $CREATE_DEPLOYMENT = 'create_deployment'; - public static string $GET_DEPLOYMENTS = 'list_deployments'; - public static string $GET_DEPLOYMENT = 'get_deployment'; - public static string $UPDATE_DEPLOYMENT = 'update_deployment'; - public static string $DELETE_DEPLOYMENT = 'delete_deployment'; - // Executions public static string $GET_EXECUTIONS = 'list_executions'; - public static string $GET_EXECUTION = 'get_execution'; - public static string $CREATE_EXECUTION = 'create_execution'; - public static string $DELETE_EXECUTION = 'delete_execution'; - public static string $RETRY_BUILD = 'retry_build'; // Buckets public static string $CREATE_BUCKET = 'create_bucket'; - public static string $GET_BUCKETS = 'list_buckets'; - public static string $GET_BUCKET = 'get_bucket'; - public static string $UPDATE_BUCKET = 'update_bucket'; - public static string $DELETE_BUCKET = 'delete_bucket'; - // Files public static string $CREATE_FILE = 'create_file'; - public static string $GET_FILES = 'list_files'; - public static string $GET_FILE = 'get_file'; - public static string $GET_FILE_PREVIEW = 'get_file_preview'; - public static string $GET_FILE_DOWNLOAD = 'get_file_download'; - public static string $GET_FILE_VIEW = 'get_file_view'; - public static string $UPDATE_FILE = 'update_file'; - public static string $DELETE_FILE = 'delete_file'; // Health public static string $GET_HTTP_HEALTH = 'get_http_health'; - public static string $GET_DB_HEALTH = 'get_db_health'; - public static string $GET_CACHE_HEALTH = 'get_cache_health'; - public static string $GET_TIME_HEALTH = 'get_time_health'; - public static string $GET_WEBHOOKS_QUEUE_HEALTH = 'get_webhooks_queue_health'; - public static string $GET_LOGS_QUEUE_HEALTH = 'get_logs_queue_health'; - public static string $GET_CERTIFICATES_QUEUE_HEALTH = 'get_certificates_queue_health'; - public static string $GET_FUNCTION_QUEUE_HEALTH = 'get_functions_queue_health'; - public static string $GET_LOCAL_STORAGE_HEALTH = 'get_local_storage_health'; - public static string $GET_ANITVIRUS_HEALTH = 'get_antivirus_health'; // Localization public static string $GET_LOCALE = 'get_locale'; - public static string $LIST_COUNTRIES = 'list_countries'; - public static string $LIST_EU_COUNTRIES = 'list_eu_countries'; - public static string $LIST_COUNTRY_PHONE_CODES = 'list_country_phone_codes'; - public static string $LIST_CONTINENTS = 'list_continents'; - public static string $LIST_CURRENCIES = 'list_currencies'; - public static string $LIST_LANGUAGES = 'list_languages'; // Avatars public static string $GET_CREDIT_CARD_ICON = 'get_credit_card_icon'; - public static string $GET_BROWSER_ICON = 'get_browser_icon'; - public static string $GET_COUNTRY_FLAG = 'get_country_flag'; - public static string $GET_IMAGE_FROM_URL = 'get_image_from_url'; - public static string $GET_FAVICON = 'get_favicon'; - public static string $GET_QRCODE = 'get_qrcode'; - public static string $GET_USER_INITIALS = 'get_user_initials'; // Complex queries @@ -745,13 +598,13 @@ trait Base ...attributeProperties } } - }'.PHP_EOL.self::$FRAGMENT_ATTRIBUTES; + }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$GET_ATTRIBUTE: return 'query getAttribute($databaseId: String!, $collectionId: String!, $key: String!) { databasesGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { ...attributeProperties } - }'.PHP_EOL.self::$FRAGMENT_ATTRIBUTES; + }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$DELETE_ATTRIBUTE: return 'mutation deleteAttribute($databaseId: String!, $collectionId: String!, $key: String!) { databasesDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { @@ -875,7 +728,7 @@ trait Base ...options } } - }'.PHP_EOL.self::$FRAGMENT_HASH_OPTIONS; + }' . PHP_EOL . self::$FRAGMENT_HASH_OPTIONS; case self::$GET_USER_PREFERENCES: return 'query getUserPreferences($userId : String!) { usersGetPrefs(userId : $userId) { @@ -2070,7 +1923,7 @@ trait Base data } } - }'.PHP_EOL.self::$FRAGMENT_ATTRIBUTES; + }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; } throw new \InvalidArgumentException('Invalid query type'); diff --git a/tests/e2e/Services/GraphQL/BatchTest.php b/tests/e2e/Services/GraphQL/BatchTest.php index a6f1da2908..7082d23677 100644 --- a/tests/e2e/Services/GraphQL/BatchTest.php +++ b/tests/e2e/Services/GraphQL/BatchTest.php @@ -63,7 +63,7 @@ class BatchTest extends Scope public function testArrayBatchedMutations() { $projectId = $this->getProject()['$id']; - $email = 'tester'.\uniqid().'@example.com'; + $email = 'tester' . \uniqid() . '@example.com'; $graphQLPayload = [[ 'query' => 'mutation CreateAccount($userId: String!, $email: String!, $password: String!, $name: String) { accountCreate(userId: $userId, email: $email, password: $password, name: $name) { @@ -77,17 +77,17 @@ class BatchTest extends Scope 'name' => 'Tester 1', ], ], - [ - 'query' => 'mutation CreateTeam($teamId: String! $name: String!) { + [ + 'query' => 'mutation CreateTeam($teamId: String! $name: String!) { teamsCreate(teamId: $teamId, name: $name) { name } }', - 'variables' => [ - 'teamId' => ID::unique(), - 'name' => 'Team 1', - ], - ], ]; + 'variables' => [ + 'teamId' => ID::unique(), + 'name' => 'Team 1', + ], + ]]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', @@ -107,8 +107,8 @@ class BatchTest extends Scope public function testArrayBatchedMutationsOfSameType() { $projectId = $this->getProject()['$id']; - $email1 = 'tester'.\uniqid().'@example.com'; - $email2 = 'tester'.\uniqid().'@example.com'; + $email1 = 'tester' . \uniqid() . '@example.com'; + $email2 = 'tester' . \uniqid() . '@example.com'; $query = 'mutation CreateAccount($userId: String!, $email: String!, $password: String!, $name: String) { accountCreate(userId: $userId, email: $email, password: $password, name: $name) { _id @@ -152,7 +152,7 @@ class BatchTest extends Scope public function testArrayBatchedMixed() { $projectId = $this->getProject()['$id']; - $email = 'tester'.\uniqid().'@example.com'; + $email = 'tester' . \uniqid() . '@example.com'; $graphQLPayload = [ ['query' => 'query { localeListCountries { total countries { code } } }'], ['query' => 'query { localeListContinents { total continents { code } } }'], @@ -167,7 +167,7 @@ class BatchTest extends Scope 'email' => $email, 'password' => 'password', 'name' => 'Tester 1', - ], + ] ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -192,7 +192,7 @@ class BatchTest extends Scope public function testArrayBatchedMixedOfSameType() { $projectId = $this->getProject()['$id']; - $email = 'tester'.\uniqid().'@example.com'; + $email = 'tester' . \uniqid() . '@example.com'; $query = 'query { localeListCountries { total countries { code } } }'; $graphQLPayload = [ ['query' => $query], @@ -208,7 +208,7 @@ class BatchTest extends Scope 'email' => $email, 'password' => 'password', 'name' => 'Tester 1', - ], + ] ], ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -281,7 +281,7 @@ class BatchTest extends Scope public function testQueryBatchedMutations() { $projectId = $this->getProject()['$id']; - $email = 'tester'.\uniqid().'@example.com'; + $email = 'tester' . \uniqid() . '@example.com'; $graphQLPayload = [ 'query' => 'mutation CreateAndLogin($userId: String!, $email: String!, $password: String!, $name: String) { accountCreate(userId: $userId, email: $email, password: $password, name: $name) { @@ -304,6 +304,7 @@ class BatchTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $graphQLPayload); + $this->assertIsArray($response['body']['data']); $this->assertArrayNotHasKey('errors', $response['body']); $this->assertArrayHasKey('accountCreate', $response['body']['data']); @@ -314,8 +315,8 @@ class BatchTest extends Scope public function testQueryBatchedMutationsOfSameType() { $projectId = $this->getProject()['$id']; - $email1 = 'tester'.\uniqid().'@example.com'; - $email2 = 'tester'.\uniqid().'@example.com'; + $email1 = 'tester' . \uniqid() . '@example.com'; + $email2 = 'tester' . \uniqid() . '@example.com'; $graphQLPayload = [ 'query' => 'mutation CreateAndLogin($email1: String!, $email2: String!, $password: String!, $name1: String, $name2: String) { accountCreate(userId: "unique()", email: $email1, password: $password, name: $name1) { @@ -346,8 +347,8 @@ class BatchTest extends Scope public function testQueryBatchedMutationsOfSameTypeWithAlias() { $projectId = $this->getProject()['$id']; - $email1 = 'tester'.\uniqid().'@example.com'; - $email2 = 'tester'.\uniqid().'@example.com'; + $email1 = 'tester' . \uniqid() . '@example.com'; + $email2 = 'tester' . \uniqid() . '@example.com'; $graphQLPayload = [ 'query' => 'mutation CreateAndLogin($email1: String!, $email2: String!, $password: String!, $name1: String, $name2: String) { account1: accountCreate(userId: "unique()", email: $email1, password: $password, name: $name1) { diff --git a/tests/e2e/Services/GraphQL/ContentTypeTest.php b/tests/e2e/Services/GraphQL/ContentTypeTest.php index 5ab950d893..da885a2a83 100644 --- a/tests/e2e/Services/GraphQL/ContentTypeTest.php +++ b/tests/e2e/Services/GraphQL/ContentTypeTest.php @@ -115,7 +115,7 @@ class ContentTypeTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', @@ -138,12 +138,12 @@ class ContentTypeTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]), 'map' => \json_encode([ - 'file' => ['variables.file'], + 'file' => ["variables.file"] ]), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/DatabaseClientTest.php index ae3b908330..3853a3fc17 100644 --- a/tests/e2e/Services/GraphQL/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseClientTest.php @@ -25,7 +25,7 @@ class DatabaseClientTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -62,7 +62,7 @@ class DatabaseClientTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - ], + ] ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -97,7 +97,7 @@ class DatabaseClientTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -129,7 +129,7 @@ class DatabaseClientTest extends Scope 'min' => 18, 'max' => 150, 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -170,7 +170,7 @@ class DatabaseClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -193,7 +193,6 @@ class DatabaseClientTest extends Scope /** * @depends testCreateCollection - * * @throws \Exception */ public function testGetDocuments($data): void @@ -205,7 +204,7 @@ class DatabaseClientTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ], + ] ]; $documents = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -220,7 +219,6 @@ class DatabaseClientTest extends Scope /** * @depends testCreateDocument - * * @throws \Exception */ public function testGetDocument($data): void @@ -233,7 +231,7 @@ class DatabaseClientTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -248,7 +246,6 @@ class DatabaseClientTest extends Scope /** * @depends testCreateDocument - * * @throws \Exception */ public function testUpdateDocument($data): void @@ -264,7 +261,7 @@ class DatabaseClientTest extends Scope 'data' => [ 'name' => 'New Document Name', ], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -282,7 +279,6 @@ class DatabaseClientTest extends Scope /** * @depends testCreateDocument - * * @throws \Exception */ public function testDeleteDocument($data): void @@ -295,7 +291,7 @@ class DatabaseClientTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ diff --git a/tests/e2e/Services/GraphQL/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/DatabaseServerTest.php index f17159c174..87006a1bea 100644 --- a/tests/e2e/Services/GraphQL/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseServerTest.php @@ -27,7 +27,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => 'actors', 'name' => 'Actors', - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -63,7 +63,7 @@ class DatabaseServerTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - ], + ] ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -89,7 +89,7 @@ class DatabaseServerTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - ], + ] ]; $collection2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -111,7 +111,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateStringAttribute($data): array @@ -126,7 +125,7 @@ class DatabaseServerTest extends Scope 'key' => 'name', 'size' => 256, 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -143,7 +142,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateStringAttribute - * * @throws Exception */ public function testUpdateStringAttribute($data): array @@ -161,7 +159,7 @@ class DatabaseServerTest extends Scope 'key' => 'name', 'required' => false, 'default' => 'Default Value', - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -180,7 +178,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateIntegerAttribute($data): array @@ -196,7 +193,7 @@ class DatabaseServerTest extends Scope 'min' => 18, 'max' => 150, 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -213,7 +210,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIntegerAttribute - * * @throws Exception */ public function testUpdateIntegerAttribute($data): array @@ -232,8 +228,8 @@ class DatabaseServerTest extends Scope 'required' => false, 'min' => 12, 'max' => 160, - 'default' => 50, - ], + 'default' => 50 + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -254,7 +250,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateBooleanAttribute($data): array @@ -268,7 +263,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'alive', 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -285,7 +280,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateBooleanAttribute - * * @throws Exception */ public function testUpdateBooleanAttribute($data): array @@ -302,8 +296,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'alive', 'required' => false, - 'default' => true, - ], + 'default' => true + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -322,7 +316,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateFloatAttribute($data): array @@ -339,7 +332,7 @@ class DatabaseServerTest extends Scope 'max' => 999999.99, 'default' => 1000.0, 'required' => false, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -356,7 +349,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateFloatAttribute - * * @throws Exception */ public function testUpdateFloatAttribute($data): array @@ -375,8 +367,8 @@ class DatabaseServerTest extends Scope 'required' => false, 'min' => 100.0, 'max' => 1000000.0, - 'default' => 2500.0, - ], + 'default' => 2500.0 + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -397,7 +389,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateEmailAttribute($data): array @@ -411,7 +402,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'email', 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -428,7 +419,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateEmailAttribute - * * @throws Exception */ public function testUpdateEmailAttribute($data): array @@ -446,7 +436,7 @@ class DatabaseServerTest extends Scope 'key' => 'email', 'required' => false, 'default' => 'torsten@appwrite.io', - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -465,7 +455,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateEnumAttribute($data): array @@ -484,7 +473,7 @@ class DatabaseServerTest extends Scope 'guest', ], 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -499,9 +488,9 @@ class DatabaseServerTest extends Scope return $data; } + /** * @depends testCreateEnumAttribute - * * @throws Exception */ public function testUpdateEnumAttribute($data): array @@ -521,10 +510,10 @@ class DatabaseServerTest extends Scope 'elements' => [ 'crew', 'tech', - 'actor', + 'actor' ], - 'default' => 'tech', - ], + 'default' => 'tech' + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -545,7 +534,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateDatetimeAttribute($data): array @@ -559,7 +547,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'dob', 'required' => true, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -576,7 +564,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatetimeAttribute - * * @throws Exception */ public function testUpdateDatetimeAttribute($data): array @@ -593,8 +580,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'dob', 'required' => false, - 'default' => '2000-01-01T00:00:00Z', - ], + 'default' => '2000-01-01T00:00:00Z' + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -627,8 +614,8 @@ class DatabaseServerTest extends Scope 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'actors', - 'twoWayKey' => 'movie', - ], + 'twoWayKey' => 'movie' + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -659,7 +646,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection2']['_id'], 'key' => 'actors', 'onDelete' => Database::RELATION_MUTATE_CASCADE, - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -676,7 +663,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateIPAttribute($data): array @@ -691,7 +677,7 @@ class DatabaseServerTest extends Scope 'key' => 'ip', 'required' => false, 'default' => '::1', - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -708,7 +694,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIPAttribute - * * @throws Exception */ public function testUpdateIPAttribute($data): array @@ -725,8 +710,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'ip', 'required' => false, - 'default' => '127.0.0.1', - ], + 'default' => '127.0.0.1' + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -745,7 +730,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testCreateURLAttribute($data): array @@ -760,7 +744,7 @@ class DatabaseServerTest extends Scope 'key' => 'url', 'required' => false, 'default' => 'https://appwrite.io', - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -777,7 +761,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateURLAttribute - * * @throws Exception */ public function testUpdateURLAttribute($data): void @@ -794,8 +777,8 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'key' => 'url', 'required' => false, - 'default' => 'https://cloud.appwrite.io', - ], + 'default' => 'https://cloud.appwrite.io' + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -813,7 +796,6 @@ class DatabaseServerTest extends Scope /** * @depends testUpdateStringAttribute * @depends testUpdateIntegerAttribute - * * @throws Exception */ public function testCreateIndex($data): array @@ -831,7 +813,7 @@ class DatabaseServerTest extends Scope 'name', 'age', ], - ], + ] ]; $index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -855,7 +837,6 @@ class DatabaseServerTest extends Scope * @depends testUpdateIntegerAttribute * @depends testUpdateBooleanAttribute * @depends testUpdateEnumAttribute - * * @throws Exception */ public function testCreateDocument($data): array @@ -882,7 +863,7 @@ class DatabaseServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -963,7 +944,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase - * * @throws Exception */ public function testGetDatabase($database): void @@ -974,7 +954,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -989,7 +969,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testGetCollections($data): void @@ -1000,7 +979,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - ], + ] ]; $collections = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1015,7 +994,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testGetCollection($data): void @@ -1027,7 +1005,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ], + ] ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1043,7 +1021,6 @@ class DatabaseServerTest extends Scope /** * @depends testUpdateStringAttribute * @depends testUpdateIntegerAttribute - * * @throws Exception */ public function testGetAttributes($data): void @@ -1055,7 +1032,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ], + ] ]; $attributes = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1070,7 +1047,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testGetAttribute($data): void @@ -1083,7 +1059,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'key' => 'name', - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1098,7 +1074,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIndex - * * @throws Exception */ public function testGetIndexes($data): void @@ -1110,7 +1085,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ], + ] ]; $indices = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1125,7 +1100,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateIndex - * * @throws Exception */ public function testGetIndex($data): void @@ -1138,7 +1112,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'key' => $data['index']['key'], - ], + ] ]; $index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1153,7 +1127,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testGetDocuments($data): void @@ -1165,7 +1138,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ], + ] ]; $documents = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1180,7 +1153,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDocument - * * @throws Exception */ public function testGetDocument($data): void @@ -1193,7 +1165,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1255,7 +1227,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase - * * @throws Exception */ public function testUpdateDatabase($database) @@ -1267,7 +1238,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $database['_id'], 'name' => 'New Database Name', - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1282,7 +1253,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testUpdateCollection($data) @@ -1296,7 +1266,7 @@ class DatabaseServerTest extends Scope 'collectionId' => $data['collection']['_id'], 'name' => 'New Collection Name', 'documentSecurity' => false, - ], + ] ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1311,7 +1281,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDocument - * * @throws Exception */ public function testUpdateDocument($data): void @@ -1327,7 +1296,7 @@ class DatabaseServerTest extends Scope 'data' => [ 'name' => 'New Document Name', ], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1372,7 +1341,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDocument - * * @throws Exception */ public function testDeleteDocument($data): void @@ -1385,7 +1353,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'documentId' => $data['document']['_id'], - ], + ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1423,7 +1391,6 @@ class DatabaseServerTest extends Scope /** * @depends testUpdateStringAttribute - * * @throws Exception */ public function testDeleteAttribute($data): void @@ -1436,7 +1403,7 @@ class DatabaseServerTest extends Scope 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], 'key' => 'name', - ], + ] ]; $attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1450,7 +1417,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateCollection - * * @throws Exception */ public function testDeleteCollection($data) @@ -1462,7 +1428,7 @@ class DatabaseServerTest extends Scope 'variables' => [ 'databaseId' => $data['database']['_id'], 'collectionId' => $data['collection']['_id'], - ], + ] ]; $collection = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ @@ -1476,7 +1442,6 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase - * * @throws Exception */ public function testDeleteDatabase($database) @@ -1487,7 +1452,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ diff --git a/tests/e2e/Services/GraphQL/FunctionsClientTest.php b/tests/e2e/Services/GraphQL/FunctionsClientTest.php index 97cbfa9206..d5b50250d4 100644 --- a/tests/e2e/Services/GraphQL/FunctionsClientTest.php +++ b/tests/e2e/Services/GraphQL/FunctionsClientTest.php @@ -27,7 +27,7 @@ class FunctionsClientTest extends Scope 'name' => 'Test Function', 'runtime' => 'php-8.0', 'execute' => [Role::any()->toString()], - ], + ] ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -36,6 +36,7 @@ class FunctionsClientTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); + $this->assertIsArray($function['body']['data']); $this->assertArrayNotHasKey('errors', $function['body']); @@ -56,7 +57,7 @@ class FunctionsClientTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $functionId, - ], + ] ]; $variables = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -73,17 +74,15 @@ class FunctionsClientTest extends Scope /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testCreateDeployment($function): array { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_DEPLOYMENT); - $code = realpath(__DIR__.'/../../../resources/functions').'/php/code.tar.gz'; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/php/code.tar.gz"; $gqlPayload = [ 'operations' => \json_encode([ 'query' => $query, @@ -92,10 +91,10 @@ class FunctionsClientTest extends Scope 'entrypoint' => 'index.php', 'activate' => true, 'code' => null, - ], + ] ]), 'map' => \json_encode([ - 'code' => ['variables.code'], + 'code' => ["variables.code"] ]), 'code' => new CURLFile($code, 'application/gzip', 'code.tar.gz'), ]; @@ -117,11 +116,9 @@ class FunctionsClientTest extends Scope /** * @depends testCreateFunction * @depends testCreateDeployment - * * @param $function * @param $deployment * @return array - * * @throws \Exception */ public function testCreateExecution($function, $deployment): array @@ -132,7 +129,7 @@ class FunctionsClientTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -142,16 +139,13 @@ class FunctionsClientTest extends Scope $this->assertIsArray($execution['body']['data']); $this->assertArrayNotHasKey('errors', $execution['body']); - return $execution['body']['data']['functionsCreateExecution']; } /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testGetExecutions($function): array @@ -162,7 +156,7 @@ class FunctionsClientTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $executions = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -181,11 +175,9 @@ class FunctionsClientTest extends Scope /** * @depends testCreateFunction * @depends testCreateExecution - * * @param $function * @param $execution * @return array - * * @throws \Exception */ public function testGetExecution($function, $execution): array @@ -197,7 +189,7 @@ class FunctionsClientTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'executionId' => $execution['_id'], - ], + ] ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/FunctionsServerTest.php b/tests/e2e/Services/GraphQL/FunctionsServerTest.php index 2771505ba7..75aa0d5d04 100644 --- a/tests/e2e/Services/GraphQL/FunctionsServerTest.php +++ b/tests/e2e/Services/GraphQL/FunctionsServerTest.php @@ -27,7 +27,7 @@ class FunctionsServerTest extends Scope 'name' => 'Test Function', 'runtime' => 'php-8.0', 'execute' => [Role::any()->toString()], - ], + ] ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -55,7 +55,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $functionId, - ], + ] ]; $variables = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -72,17 +72,15 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testCreateDeployment($function): array { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_DEPLOYMENT); - $code = realpath(__DIR__.'/../../../resources/functions').'/php/code.tar.gz'; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/php/code.tar.gz"; $gqlPayload = [ 'operations' => \json_encode([ 'query' => $query, @@ -91,10 +89,10 @@ class FunctionsServerTest extends Scope 'entrypoint' => 'index.php', 'activate' => true, 'code' => null, - ], + ] ]), 'map' => \json_encode([ - 'code' => ['variables.code'], + 'code' => ["variables.code"] ]), 'code' => new CURLFile($code, 'application/gzip', 'code.tar.gz'), ]; @@ -115,10 +113,8 @@ class FunctionsServerTest extends Scope /** * * @depends testCreateFunction * @depends testCreateDeployment - * * @param $function * @return array - * * @throws \Exception */ public function testCreateExecution($function): array @@ -129,7 +125,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -146,11 +142,9 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testGetDeployment - * * @param $function * @param $deployment * @return array - * * @throws \Exception */ public function testCreateRetryBuild($function, $deployment): void @@ -163,7 +157,7 @@ class FunctionsServerTest extends Scope 'functionId' => $function['_id'], 'deploymentId' => $deployment['_id'], 'buildId' => $deployment['buildId'], - ], + ] ]; $retryBuild = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -172,7 +166,7 @@ class FunctionsServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($retryBuild['body']['errors']); - $this->assertEquals('Build not failed', $retryBuild['body']['errors'][0]['message']); + $this->assertEquals("Build not failed", $retryBuild['body']['errors'][0]['message']); } public function testGetFunctions(): array @@ -198,10 +192,8 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testGetFunction($function): array @@ -212,7 +204,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -251,10 +243,8 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testGetDeployments($function) @@ -265,7 +255,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $deployments = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -284,10 +274,8 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testCreateDeployment - * * @param $function * @return array - * * @throws \Exception */ public function testGetDeployment($function, $deployment) @@ -299,7 +287,7 @@ class FunctionsServerTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'deploymentId' => $deployment['_id'], - ], + ] ]; $deployment = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -317,10 +305,8 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testGetExecutions($function): array @@ -331,7 +317,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $executions = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -350,11 +336,9 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testCreateExecution - * * @param $function * @param $execution * @return array - * * @throws \Exception */ public function testGetExecution($function, $execution): array @@ -366,7 +350,7 @@ class FunctionsServerTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'executionId' => $execution['_id'], - ], + ] ]; $execution = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -384,10 +368,8 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction - * * @param $function * @return array - * * @throws \Exception */ public function testUpdateFunction($function): array @@ -404,7 +386,7 @@ class FunctionsServerTest extends Scope 'name' => 'John Doe', 'age' => 42, ], - ], + ] ]; $function = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -423,10 +405,8 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testCreateDeployment - * * @param $function * @param $deployment - * * @throws \Exception */ public function testDeleteDeployment($function, $deployment): void @@ -438,7 +418,7 @@ class FunctionsServerTest extends Scope 'variables' => [ 'functionId' => $function['_id'], 'deploymentId' => $deployment['_id'], - ], + ] ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -453,9 +433,7 @@ class FunctionsServerTest extends Scope /** * @depends testCreateFunction * @depends testDeleteDeployment - * * @param $function - * * @throws \Exception */ public function testDeleteFunction($function): void @@ -466,7 +444,7 @@ class FunctionsServerTest extends Scope 'query' => $query, 'variables' => [ 'functionId' => $function['_id'], - ], + ] ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/LocalizationTest.php b/tests/e2e/Services/GraphQL/LocalizationTest.php index 2fe76a6f06..38200911c8 100644 --- a/tests/e2e/Services/GraphQL/LocalizationTest.php +++ b/tests/e2e/Services/GraphQL/LocalizationTest.php @@ -18,7 +18,7 @@ class LocalizationTest extends Scope $projectId = $this->getProject()['$id']; $query = \urlencode($this->getQuery(self::$GET_LOCALE)); - $locale = $this->client->call(Client::METHOD_GET, '/graphql?query='.$query, \array_merge([ + $locale = $this->client->call(Client::METHOD_GET, '/graphql?query=' . $query, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders())); diff --git a/tests/e2e/Services/GraphQL/ScopeTest.php b/tests/e2e/Services/GraphQL/ScopeTest.php index 44122887da..a8b5b7cea4 100644 --- a/tests/e2e/Services/GraphQL/ScopeTest.php +++ b/tests/e2e/Services/GraphQL/ScopeTest.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\GraphQL; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\SideClient; use Tests\E2E\Scopes\SideServer; use Utopia\Database\Helpers\ID; @@ -24,7 +25,7 @@ class ScopeTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -48,7 +49,7 @@ class ScopeTest extends Scope 'variables' => [ 'databaseId' => ID::unique(), 'name' => 'Actors', - ], + ] ]; $database = $this->client->call(Client::METHOD_POST, '/graphql', [ diff --git a/tests/e2e/Services/GraphQL/StorageClientTest.php b/tests/e2e/Services/GraphQL/StorageClientTest.php index 90cfaef7d5..9896598c2d 100644 --- a/tests/e2e/Services/GraphQL/StorageClientTest.php +++ b/tests/e2e/Services/GraphQL/StorageClientTest.php @@ -33,7 +33,7 @@ class StorageClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -70,12 +70,12 @@ class StorageClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]), 'map' => \json_encode([ - '0' => ['variables.file'], + '0' => ["variables.file"] ]), - '0' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + '0' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -91,10 +91,8 @@ class StorageClientTest extends Scope /** * @depends testCreateBucket - * * @param $bucket * @return array - * * @throws \Exception */ public function testGetFiles($bucket): array @@ -105,7 +103,7 @@ class StorageClientTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ], + ] ]; $files = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -124,11 +122,9 @@ class StorageClientTest extends Scope /** * @depends testCreateBucket * @depends testCreateFile - * * @param $bucket * @param $file * @return array - * * @throws \Exception */ public function testGetFile($bucket, $file) @@ -140,7 +136,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $bucket['_id'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -156,10 +152,8 @@ class StorageClientTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testGetFilePreview($file) @@ -173,7 +167,7 @@ class StorageClientTest extends Scope 'fileId' => $file['_id'], 'width' => 100, 'height' => 100, - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -188,10 +182,8 @@ class StorageClientTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testGetFileDownload($file) @@ -203,7 +195,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -216,10 +208,8 @@ class StorageClientTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testGetFileView($file): void @@ -231,7 +221,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -244,10 +234,8 @@ class StorageClientTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testUpdateFile($file): array @@ -264,7 +252,7 @@ class StorageClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -282,9 +270,7 @@ class StorageClientTest extends Scope /** * @depends testCreateFile - * * @param $file - * * @throws \Exception */ public function testDeleteFile($file): void @@ -296,7 +282,7 @@ class StorageClientTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/StorageServerTest.php b/tests/e2e/Services/GraphQL/StorageServerTest.php index c4c12e400c..7fea895b1c 100644 --- a/tests/e2e/Services/GraphQL/StorageServerTest.php +++ b/tests/e2e/Services/GraphQL/StorageServerTest.php @@ -33,7 +33,7 @@ class StorageServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -69,12 +69,12 @@ class StorageServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]), 'map' => \json_encode([ - 'file' => ['variables.file'], + 'file' => ["variables.file"] ]), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -84,7 +84,6 @@ class StorageServerTest extends Scope $this->assertIsArray($file['body']['data']); $this->assertArrayNotHasKey('errors', $file['body']); - return $file['body']['data']['storageCreateFile']; } @@ -111,10 +110,8 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket - * * @param $bucket * @return array - * * @throws \Exception */ public function testGetBucket($bucket): array @@ -125,7 +122,7 @@ class StorageServerTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ], + ] ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -143,10 +140,8 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket - * * @param $bucket * @return array - * * @throws \Exception */ public function testGetFiles($bucket): array @@ -157,7 +152,7 @@ class StorageServerTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ], + ] ]; $files = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -176,11 +171,9 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket * @depends testCreateFile - * * @param $bucket * @param $file * @return array - * * @throws \Exception */ public function testGetFile($bucket, $file) @@ -192,7 +185,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $bucket['_id'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -208,10 +201,8 @@ class StorageServerTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testGetFilePreview($file) @@ -225,7 +216,7 @@ class StorageServerTest extends Scope 'fileId' => $file['_id'], 'width' => 100, 'height' => 100, - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -240,10 +231,8 @@ class StorageServerTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testGetFileDownload($file) @@ -255,7 +244,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -268,10 +257,8 @@ class StorageServerTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testGetFileView($file): void @@ -283,7 +270,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -296,10 +283,8 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket - * * @param $bucket * @return array - * * @throws \Exception */ public function testUpdateBucket($bucket): array @@ -312,7 +297,7 @@ class StorageServerTest extends Scope 'bucketId' => $bucket['_id'], 'name' => 'Actors Updated', 'fileSecurity' => false, - ], + ] ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -330,10 +315,8 @@ class StorageServerTest extends Scope /** * @depends testCreateFile - * * @param $file * @return array - * * @throws \Exception */ public function testUpdateFile($file): array @@ -350,7 +333,7 @@ class StorageServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -368,9 +351,7 @@ class StorageServerTest extends Scope /** * @depends testCreateFile - * * @param $file - * * @throws \Exception */ public function testDeleteFile($file): void @@ -382,7 +363,7 @@ class StorageServerTest extends Scope 'variables' => [ 'bucketId' => $file['bucketId'], 'fileId' => $file['_id'], - ], + ] ]; $file = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -396,10 +377,8 @@ class StorageServerTest extends Scope /** * @depends testCreateBucket - * * @param $bucket * @return array - * * @throws \Exception */ public function testDeleteBucket($bucket): void @@ -410,7 +389,7 @@ class StorageServerTest extends Scope 'query' => $query, 'variables' => [ 'bucketId' => $bucket['_id'], - ], + ] ]; $bucket = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/TeamsServerTest.php b/tests/e2e/Services/GraphQL/TeamsServerTest.php index a8d8f64ac6..33c7847113 100644 --- a/tests/e2e/Services/GraphQL/TeamsServerTest.php +++ b/tests/e2e/Services/GraphQL/TeamsServerTest.php @@ -125,10 +125,10 @@ class TeamsServerTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'teamId' => $team['_id'], + 'teamId' => $team['_id'], 'prefs' => [ - 'key' => 'value', - ], + 'key' => 'value' + ] ], ]; @@ -156,7 +156,7 @@ class TeamsServerTest extends Scope 'query' => $query, 'variables' => [ 'teamId' => $team['_id'], - ], + ] ]; $prefs = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/GraphQL/UsersTest.php b/tests/e2e/Services/GraphQL/UsersTest.php index e965fc5899..9bd503df0f 100644 --- a/tests/e2e/Services/GraphQL/UsersTest.php +++ b/tests/e2e/Services/GraphQL/UsersTest.php @@ -7,6 +7,7 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; class UsersTest extends Scope { @@ -26,7 +27,7 @@ class UsersTest extends Scope 'email' => $email, 'password' => 'password', 'name' => 'Project User', - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -55,7 +56,7 @@ class UsersTest extends Scope 'limit(100)', 'offset(0)', ], - ], + ] ]; $users = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -77,7 +78,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -99,7 +100,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -120,7 +121,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -141,7 +142,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -162,7 +163,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -184,7 +185,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'status' => true, - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -207,7 +208,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'emailVerification' => true, - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -229,7 +230,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'phoneVerification' => true, - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -252,7 +253,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'name' => 'Updated Name', - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -274,7 +275,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - 'email' => 'newemail@appwrite.io', + 'email' => 'newemail@appwrite.io' ], ]; @@ -297,7 +298,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - 'password' => 'newpassword', + 'password' => 'newpassword' ], ]; @@ -319,7 +320,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - 'number' => '+123456789', + 'number' => '+123456789' ], ]; @@ -343,8 +344,8 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'prefs' => [ - 'key' => 'value', - ], + 'key' => 'value' + ] ], ]; @@ -367,7 +368,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -391,7 +392,7 @@ class UsersTest extends Scope 'variables' => [ 'userId' => $this->getUser()['$id'], 'sessionId' => $this->getUser()['sessionId'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ @@ -414,7 +415,7 @@ class UsersTest extends Scope 'query' => $query, 'variables' => [ 'userId' => $this->getUser()['$id'], - ], + ] ]; $user = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ diff --git a/tests/e2e/Services/Health/HealthBase.php b/tests/e2e/Services/Health/HealthBase.php index 545cbc893f..cbd0f97668 100644 --- a/tests/e2e/Services/Health/HealthBase.php +++ b/tests/e2e/Services/Health/HealthBase.php @@ -2,6 +2,8 @@ namespace Tests\E2E\Services\Health; +use Tests\E2E\Client; + trait HealthBase { } diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 23b9833c96..96c9bde5c7 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -3,8 +3,9 @@ namespace Tests\E2E\Services\Health; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\SideClient; use Tests\E2E\Scopes\SideServer; class HealthCustomServerTest extends Scope diff --git a/tests/e2e/Services/Locale/LocaleBase.php b/tests/e2e/Services/Locale/LocaleBase.php index 38d6a61fd5..17b5c66d67 100644 --- a/tests/e2e/Services/Locale/LocaleBase.php +++ b/tests/e2e/Services/Locale/LocaleBase.php @@ -100,6 +100,7 @@ trait LocaleBase $this->assertEquals($response['body']['countries'][0]['name'], 'Alemania'); $this->assertEquals($response['body']['countries'][0]['code'], 'DE'); + /** * Test for FAILURE */ @@ -161,6 +162,7 @@ trait LocaleBase $this->assertEquals($response['body']['continents'][0]['code'], 'NA'); $this->assertEquals($response['body']['continents'][0]['name'], 'América del Norte'); + /** * Test for FAILURE */ @@ -225,9 +227,9 @@ trait LocaleBase /** * Test for SUCCESS */ - $languages = require 'app/config/locale/codes.php'; - $defaultCountries = require 'app/config/locale/countries.php'; - $defaultContinents = require 'app/config/locale/continents.php'; + $languages = require('app/config/locale/codes.php'); + $defaultCountries = require('app/config/locale/countries.php'); + $defaultContinents = require('app/config/locale/continents.php'); foreach ($languages as $lang) { $response = $this->client->call(Client::METHOD_GET, '/locale/countries', [ @@ -236,12 +238,12 @@ trait LocaleBase 'x-appwrite-locale' => $lang['code'], ]); - if (! \is_array($response['body']['countries'])) { - throw new Exception('Failed to iterate locale: '.$lang); + if (!\is_array($response['body']['countries'])) { + throw new Exception('Failed to iterate locale: ' . $lang); } foreach ($response['body']['countries'] as $i => $code) { - $this->assertContains($code['code'], $defaultCountries, $code['code'].' country should be removed from '.$lang['code']); + $this->assertContains($code['code'], $defaultCountries, $code['code'] . ' country should be removed from ' . $lang['code']); } $this->assertEquals($response['headers']['status-code'], 200); @@ -254,7 +256,7 @@ trait LocaleBase ]); foreach ($response['body']['continents'] as $i => $code) { - $this->assertContains($code['code'], $defaultContinents, $code['code'].' continent should be removed from '.$lang['code']); + $this->assertContains($code['code'], $defaultContinents, $code['code'] . ' continent should be removed from ' . $lang['code']); } $this->assertEquals($response['headers']['status-code'], 200); diff --git a/tests/e2e/Services/Locale/LocaleConsoleClientTest.php b/tests/e2e/Services/Locale/LocaleConsoleClientTest.php index c72e554df7..29b3150fed 100644 --- a/tests/e2e/Services/Locale/LocaleConsoleClientTest.php +++ b/tests/e2e/Services/Locale/LocaleConsoleClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Locale; -use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; class LocaleConsoleClientTest extends Scope diff --git a/tests/e2e/Services/Locale/LocaleCustomClientTest.php b/tests/e2e/Services/Locale/LocaleCustomClientTest.php index 6d6108dec1..b28584280e 100644 --- a/tests/e2e/Services/Locale/LocaleCustomClientTest.php +++ b/tests/e2e/Services/Locale/LocaleCustomClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Locale; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; class LocaleCustomClientTest extends Scope diff --git a/tests/e2e/Services/Locale/LocaleCustomServerTest.php b/tests/e2e/Services/Locale/LocaleCustomServerTest.php index 1513f9b342..62d4e76802 100644 --- a/tests/e2e/Services/Locale/LocaleCustomServerTest.php +++ b/tests/e2e/Services/Locale/LocaleCustomServerTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Locale; +use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 8f477173eb..9bc9f93caf 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -65,7 +65,7 @@ class MessagingServerTest extends Scope $providers = []; foreach (\array_keys($providersParams) as $key) { - $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/'.$key, [ + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -132,7 +132,7 @@ class MessagingServerTest extends Scope ], ]; foreach (\array_keys($providersParams) as $index => $key) { - $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/'.$providers[$index]['$id'].'/'.$key, [ + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $providers[$index]['$id'] . '/' . $key, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -164,7 +164,7 @@ class MessagingServerTest extends Scope */ public function testGetProvider(array $providers) { - $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/'.$providers[0]['$id'], [ + $response = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $providers[0]['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -179,7 +179,7 @@ class MessagingServerTest extends Scope public function testDeleteProvider(array $providers) { foreach ($providers as $provider) { - $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/'.$provider['$id'], [ + $response = $this->client->call(Client::METHOD_DELETE, '/messaging/providers/' . $provider['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -187,4 +187,5 @@ class MessagingServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } } + } diff --git a/tests/e2e/Services/Projects/ProjectsBase.php b/tests/e2e/Services/Projects/ProjectsBase.php index 53d9626252..a9ccd73900 100644 --- a/tests/e2e/Services/Projects/ProjectsBase.php +++ b/tests/e2e/Services/Projects/ProjectsBase.php @@ -2,6 +2,8 @@ namespace Tests\E2E\Services\Projects; +use Tests\E2E\Client; + trait ProjectsBase { } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 5006ab224a..31c8c72a14 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -4,10 +4,10 @@ namespace Tests\E2E\Services\Projects; use Appwrite\Auth\Auth; use Appwrite\Extend\Exception; -use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; +use Tests\E2E\Client; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; @@ -84,7 +84,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => '', 'teamId' => $team['body']['$id'], - 'region' => 'default', + 'region' => 'default' ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -95,14 +95,14 @@ class ProjectsConsoleClientTest extends Scope ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Project Test', - 'region' => 'default', + 'region' => 'default' ]); $this->assertEquals(400, $response['headers']['status-code']); return [ 'projectId' => $projectId, - 'teamId' => $team['body']['$id'], + 'teamId' => $team['body']['$id'] ]; } @@ -124,7 +124,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => $projectId, 'name' => 'Project Duplicate', 'teamId' => $teamId, - 'region' => 'default', + 'region' => 'default' ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -187,7 +187,7 @@ class ProjectsConsoleClientTest extends Scope $projectId = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$projectId.'/team', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $projectId . '/team', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -211,6 +211,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'], @@ -228,7 +229,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => $id, + 'search' => $id ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -241,7 +242,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders(), [ - 'search' => 'Project Test', + 'search' => 'Project Test' ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -272,7 +273,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test 2', 'teamId' => $team['body']['$id'], - 'region' => 'default', + 'region' => 'default' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -287,7 +288,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("teamId", "'.$team['body']['$id'].'")'], + 'queries' => [ 'equal("teamId", "' . $team['body']['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -299,7 +300,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -311,7 +312,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(3)'], + 'queries' => [ 'offset(3)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -323,7 +324,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("name", "Project Test 2")'], + 'queries' => [ 'equal("name", "Project Test 2")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -335,7 +336,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['orderDesc("")'], + 'queries' => [ 'orderDesc("")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -359,7 +360,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$response['body']['projects'][0]['$id'].'")'], + 'queries' => [ 'cursorAfter("' . $response['body']['projects'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -371,7 +372,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("'.$response['body']['projects'][0]['$id'].'")'], + 'queries' => [ 'cursorBefore("' . $response['body']['projects'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -386,7 +387,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("unknown")'], + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -404,7 +405,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -417,6 +418,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_GET, '/projects/empty', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -465,6 +467,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_GET, '/projects/empty', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -492,7 +495,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -512,6 +515,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -532,7 +536,7 @@ class ProjectsConsoleClientTest extends Scope public function testUpdateProjectSMTP($data): array { $id = $data['projectId']; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/smtp', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/smtp', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -554,7 +558,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['smtpSecure']); /** Test Reading Project */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -569,7 +573,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['smtpSecure']); /** Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/smtp', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/smtp', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -580,7 +584,6 @@ class ProjectsConsoleClientTest extends Scope 'username' => 'user', 'password' => 'password', ]); - return $data; } @@ -592,7 +595,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId']; /** Get Default Email Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/email/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/email/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -606,7 +609,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertMatchesRegularExpression('//', $response['body']['message']); /** Update Email template */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/templates/email/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/templates/email/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -625,7 +628,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('Please verify your email {{url}}', $response['body']['message']); /** Get Updated Email Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/email/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/email/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -639,7 +642,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('Please verify your email {{url}}', $response['body']['message']); /** Get Default SMS Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/sms/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/sms/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -650,7 +653,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('{{token}}', $response['body']['message']); /** Update SMS template */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/templates/sms/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/templates/sms/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -663,7 +666,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('Please verify your email {{token}}', $response['body']['message']); /** Get Updated SMS Template */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/templates/sms/verification/en-us', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/templates/sms/verification/en-us', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -682,7 +685,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId']; // Check defaults - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); @@ -693,7 +696,8 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/duration', array_merge([ + + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/duration', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -716,7 +720,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'userId' => 'unique()', - 'email' => 'test'.rand(0, 9999).'@example.com', + 'email' => 'test' . rand(0, 9999) . '@example.com', 'password' => 'password', 'name' => 'Test User', ]); @@ -773,7 +777,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(401, $response['headers']['status-code']); // Return project back to normal - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/duration', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/duration', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -784,7 +788,7 @@ class ProjectsConsoleClientTest extends Scope $projectId = $response['body']['$id']; // Check project is back to normal - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$projectId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); @@ -801,26 +805,27 @@ class ProjectsConsoleClientTest extends Scope public function testUpdateProjectOAuth($data): array { $id = $data['projectId'] ?? ''; - $providers = require 'app/config/authProviders.php'; + $providers = require('app/config/authProviders.php'); /** * Test for SUCCESS */ + foreach ($providers as $key => $provider) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'provider' => $key, - 'appId' => 'AppId-'.ucfirst($key), - 'secret' => 'Secret-'.ucfirst($key), + 'appId' => 'AppId-' . ucfirst($key), + 'secret' => 'Secret-' . ucfirst($key), ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); } - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -833,8 +838,8 @@ class ProjectsConsoleClientTest extends Scope $asserted = false; foreach ($response['body']['providers'] as $responseProvider) { if ($responseProvider['key'] === $key) { - $this->assertEquals('AppId-'.ucfirst($key), $responseProvider['appId']); - $this->assertEquals('Secret-'.ucfirst($key), $responseProvider['secret']); + $this->assertEquals('AppId-' . ucfirst($key), $responseProvider['appId']); + $this->assertEquals('Secret-' . ucfirst($key), $responseProvider['secret']); $this->assertFalse($responseProvider['enabled']); $asserted = true; break; @@ -847,12 +852,12 @@ class ProjectsConsoleClientTest extends Scope // Enable providers $i = 0; foreach ($providers as $key => $provider) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/oauth2', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'provider' => $key, - 'enabled' => $i === 0 ? false : true, // On first provider, test enabled=false + 'enabled' => $i === 0 ? false : true // On first provider, test enabled=false ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -861,7 +866,7 @@ class ProjectsConsoleClientTest extends Scope $i++; } - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -890,7 +895,8 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/oauth2', array_merge([ + + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -910,9 +916,9 @@ class ProjectsConsoleClientTest extends Scope public function testUpdateProjectAuthStatus($data): array { $id = $data['projectId'] ?? ''; - $auth = require 'app/config/auth.php'; + $auth = require('app/config/auth.php'); - $originalEmail = uniqid().'user@localhost.test'; + $originalEmail = uniqid() . 'user@localhost.test'; $originalPassword = 'password'; $originalName = 'User Name'; @@ -936,13 +942,13 @@ class ProjectsConsoleClientTest extends Scope 'password' => $originalPassword, ]); - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$id]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $id]; /** * Test for SUCCESS */ foreach ($auth as $index => $method) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/'.$index, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/' . $index, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -952,17 +958,17 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['auth'.ucfirst($method['key'])]); + $this->assertEquals(false, $response['body']['auth' . ucfirst($method['key'])]); } - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -985,25 +991,25 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_'.$id.'='.$session, + 'cookie' => 'a_session_' . $id . '=' . $session, ]), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal', + 'name' => 'Arsenal' ]); $this->assertEquals(201, $response['headers']['status-code']); $teamUid = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_'.$id.'='.$session, + 'cookie' => 'a_session_' . $id . '=' . $session, ]), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals($response['headers']['status-code'], 501); @@ -1011,7 +1017,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/account/jwt', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_'.$id.'='.$session, + 'cookie' => 'a_session_' . $id . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 501); @@ -1038,7 +1044,7 @@ class ProjectsConsoleClientTest extends Scope // Cleanup foreach ($auth as $index => $method) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/'.$index, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/' . $index, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1059,7 +1065,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/limit', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/limit', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1069,7 +1075,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -1087,7 +1093,7 @@ class ProjectsConsoleClientTest extends Scope 'name' => $name, ]); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'origin' => 'http://localhost', @@ -1105,7 +1111,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/limit', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/limit', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1115,7 +1121,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'origin' => 'http://localhost', @@ -1143,7 +1149,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for failure */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/max-sessions', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/max-sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1155,7 +1161,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/max-sessions', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/max-sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1166,7 +1172,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertEquals(1, $response['body']['authSessionsLimit']); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -1198,6 +1204,7 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, ]); + $this->assertEquals(201, $response['headers']['status-code']); $sessionId1 = $response['body']['$id']; @@ -1213,6 +1220,7 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, ]); + $this->assertEquals(201, $response['headers']['status-code']); $sessionCookie = $response['headers']['set-cookie']; $sessionId2 = $response['body']['$id']; @@ -1239,7 +1247,7 @@ class ProjectsConsoleClientTest extends Scope /** * Reset Limit */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/max-sessions', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/max-sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1249,6 +1257,7 @@ class ProjectsConsoleClientTest extends Scope return $data; } + /** * @depends testUpdateProjectAuthLimit */ @@ -1259,7 +1268,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for Failure */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1268,10 +1277,11 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); + /** * Test for Success */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1281,7 +1291,8 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(1, $response['body']['authPasswordHistory']); - $email = uniqid().'user@localhost.test'; + + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -1313,13 +1324,13 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, ]); $this->assertEquals(201, $session['headers']['status-code']); - $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$id]; + $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $id]; $response = $this->client->call(Client::METHOD_PATCH, '/account/password', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'cookie' => 'a_session_'.$id.'='.$session, + 'cookie' => 'a_session_' . $id . '=' . $session, ]), [ 'oldPassword' => $password, 'password' => $password, @@ -1333,16 +1344,17 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]); - $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$userId.'/password', $headers, [ + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $userId . '/password', $headers, [ 'password' => $password, ]); $this->assertEquals(400, $response['headers']['status-code']); - /** + + /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1351,7 +1363,6 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(0, $response['body']['authPasswordHistory']); - return $data; } @@ -1378,7 +1389,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]), [ 'userId' => ID::unique(), - 'email' => uniqid().'user@localhost.test', + 'email' => uniqid() . 'user@localhost.test', 'password' => $password, 'name' => $name, ]); @@ -1394,7 +1405,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-mode' => 'admin', ]), [ 'userId' => ID::unique(), - 'email' => uniqid().'user@localhost.test', + 'email' => uniqid() . 'user@localhost.test', 'password' => 'password', 'name' => 'Cristiano Ronaldo', ]); @@ -1403,7 +1414,7 @@ class ProjectsConsoleClientTest extends Scope /** * Enable Disctionary */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-dictionary', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-dictionary', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1422,7 +1433,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]), [ 'userId' => ID::unique(), - 'email' => uniqid().'user@localhost.test', + 'email' => uniqid() . 'user@localhost.test', 'password' => $password, 'name' => $name, ]); @@ -1438,7 +1449,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-mode' => 'admin', ]), [ 'userId' => ID::unique(), - 'email' => uniqid().'user@localhost.test', + 'email' => uniqid() . 'user@localhost.test', 'password' => 'password', 'name' => 'Cristiano Ronaldo', ]); @@ -1450,16 +1461,17 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]); - $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$userId.'/password', $headers, [ + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $userId . '/password', $headers, [ 'password' => $password, ]); $this->assertEquals(400, $response['headers']['status-code']); - /** + + /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1472,7 +1484,7 @@ class ProjectsConsoleClientTest extends Scope /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/password-dictionary', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/password-dictionary', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1495,7 +1507,7 @@ class ProjectsConsoleClientTest extends Scope /** * Enable Disallowing of Personal Data */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/personal-data', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/personal-data', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1508,7 +1520,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for failure */ - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'username'; $userId = ID::unique(); @@ -1521,7 +1533,7 @@ class ProjectsConsoleClientTest extends Scope 'email' => $email, 'password' => $email, 'name' => $name, - 'userId' => $userId, + 'userId' => $userId ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -1536,7 +1548,7 @@ class ProjectsConsoleClientTest extends Scope 'email' => $email, 'password' => $name, 'name' => $name, - 'userId' => $userId, + 'userId' => $userId ]); $phone = '+123456789'; @@ -1549,7 +1561,7 @@ class ProjectsConsoleClientTest extends Scope 'password' => $phone, 'name' => $name, 'userId' => $userId, - 'phone' => $phone, + 'phone' => $phone ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -1557,7 +1569,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(Exception::USER_PASSWORD_PERSONAL_DATA, $response['body']['type']); /** Test for success */ - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'username'; $userId = ID::unique(); @@ -1569,12 +1581,12 @@ class ProjectsConsoleClientTest extends Scope 'email' => $email, 'password' => $password, 'name' => $name, - 'userId' => $userId, + 'userId' => $userId ]); $this->assertEquals(201, $response['headers']['status-code']); - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $userId = ID::unique(); $response = $this->client->call(Client::METHOD_POST, '/users', array_merge($this->getHeaders(), [ 'content-type' => 'application/json', @@ -1585,15 +1597,16 @@ class ProjectsConsoleClientTest extends Scope 'password' => $password, 'name' => $name, 'userId' => $userId, - 'phone' => $phone, + 'phone' => $phone ]); $this->assertEquals(201, $response['headers']['status-code']); + /** * Reset */ - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/auth/personal-data', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/auth/personal-data', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1604,12 +1617,13 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(false, $response['body']['authPersonalDataCheck']); } + public function testUpdateProjectServiceStatusAdmin(): array { $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'teamId' => ID::unique(), 'name' => 'Project Test', @@ -1620,34 +1634,34 @@ class ProjectsConsoleClientTest extends Scope $project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'projectId' => ID::unique(), 'name' => 'Project Test', 'teamId' => $team['body']['$id'], - 'region' => 'default', + 'region' => 'default' ]); $this->assertEquals(201, $project['headers']['status-code']); $this->assertNotEmpty($project['body']['$id']); $id = $project['body']['$id']; - $services = require 'app/config/services.php'; + $services = require('app/config/services.php'); /** * Test for Disabled */ foreach ($services as $service) { - if (! $service['optional']) { + if (!$service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'service' => $key, 'status' => false, @@ -1656,39 +1670,40 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['serviceStatusFor'.ucfirst($key)]); + $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); } /** * Admin request must succeed */ + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', // 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $id, - 'cookie' => 'a_session_console='.$this->getRoot()['session'], - 'x-appwrite-mode' => 'admin', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-mode' => 'admin' ])); $this->assertEquals(200, $response['headers']['status-code']); foreach ($services as $service) { - if (! $service['optional']) { + if (!$service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service/', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1705,22 +1720,22 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId']; - $services = require 'app/config/services.php'; + $services = require('app/config/services.php'); /** * Test for Disabled */ foreach ($services as $service) { - if (! $service['optional']) { + if (!$service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'service' => $key, 'status' => false, @@ -1729,15 +1744,15 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['serviceStatusFor'.ucfirst($key)]); + $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); } /** @@ -1756,7 +1771,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $id, ]), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal', + 'name' => 'Arsenal' ]); $this->assertEquals(503, $response['headers']['status-code']); @@ -1764,7 +1779,7 @@ class ProjectsConsoleClientTest extends Scope // Cleanup foreach ($services as $service) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service/', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1779,22 +1794,22 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId']; - $services = require 'app/config/services.php'; + $services = require('app/config/services.php'); /** * Test for Disabled */ foreach ($services as $service) { - if (! $service['optional']) { + if (!$service['optional']) { continue; } $key = $service['key'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'service' => $key, 'status' => false, @@ -1803,22 +1818,22 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ])); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(false, $response['body']['serviceStatusFor'.ucfirst($key)]); + $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); } // Create API Key - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), [ 'name' => 'Key Test', 'scopes' => ['functions.read', 'teams.write'], @@ -1836,7 +1851,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $id, 'x-appwrite-key' => $keySecret, - 'x-sdk-name' => 'python', + 'x-sdk-name' => 'python' ])); $this->assertEquals(200, $response['headers']['status-code']); @@ -1845,19 +1860,19 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $id, 'x-appwrite-key' => $keySecret, - 'x-sdk-name' => 'php', + 'x-sdk-name' => 'php' ]), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal', + 'name' => 'Arsenal' ]); $this->assertEquals(201, $response['headers']['status-code']); /** Check that the API key has been updated */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -1870,16 +1885,16 @@ class ProjectsConsoleClientTest extends Scope // Cleanup - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]), []); $this->assertEquals(204, $response['headers']['status-code']); foreach ($services as $service) { - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/service/', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1896,7 +1911,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1923,7 +1938,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1937,7 +1952,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1958,7 +1973,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -1981,7 +1996,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $webhookId = $data['webhookId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -1999,7 +2014,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2017,7 +2032,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $webhookId = $data['webhookId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2041,7 +2056,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['httpUser']); $this->assertEquals('', $response['body']['httpPass']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2063,7 +2078,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2075,7 +2090,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2087,7 +2102,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2110,7 +2125,7 @@ class ProjectsConsoleClientTest extends Scope $webhookId = $data['webhookId'] ?? ''; $signatureKey = $data['signatureKey'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/webhooks/'.$webhookId.'/signature', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/webhooks/' . $webhookId . '/signature', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -2128,7 +2143,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $webhookId = $data['webhookId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2136,7 +2151,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2146,7 +2161,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2165,7 +2180,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2186,13 +2201,13 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, [ 'keyId' => $response['body']['$id'], - 'secret' => $response['body']['secret'], + 'secret' => $response['body']['secret'] ]); /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2205,6 +2220,7 @@ class ProjectsConsoleClientTest extends Scope return $data; } + /** * @depends testCreateProjectKey */ @@ -2212,11 +2228,12 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); + $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(1, $response['body']['total']); @@ -2227,6 +2244,7 @@ class ProjectsConsoleClientTest extends Scope return $data; } + /** * @depends testCreateProjectKey */ @@ -2235,10 +2253,10 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $keyId = $data['keyId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $keyId, + 'x-appwrite-key' => $keyId ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2257,7 +2275,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2277,7 +2295,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2289,7 +2307,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/health', [ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'x-appwrite-key' => $response['body']['secret'], + 'x-appwrite-key' => $response['body']['secret'] ], []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2297,7 +2315,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2309,7 +2327,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/health', [ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'x-appwrite-key' => $response['body']['secret'], + 'x-appwrite-key' => $response['body']['secret'] ], []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2317,7 +2335,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/keys', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2329,12 +2347,13 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/health', [ 'content-type' => 'application/json', 'x-appwrite-project' => $id, - 'x-appwrite-key' => $response['body']['secret'], + 'x-appwrite-key' => $response['body']['secret'] ], []); $this->assertEquals(401, $response['headers']['status-code']); } + /** * @depends testCreateProjectKey */ @@ -2343,7 +2362,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $keyId = $data['keyId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2365,7 +2384,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertArrayHasKey('accessedAt', $response['body']); $this->assertEmpty($response['body']['accessedAt']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2386,7 +2405,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2407,7 +2426,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $keyId = $data['keyId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2415,7 +2434,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/keys/'.$keyId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/keys/' . $keyId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2425,7 +2444,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/keys/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2444,7 +2463,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2463,7 +2482,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformWebId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2482,7 +2501,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformFultteriOSId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2501,7 +2520,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformFultterAndroidId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2520,7 +2539,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformFultterWebId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2539,7 +2558,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformAppleIosId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2558,7 +2577,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformAppleMacOsId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2577,7 +2596,7 @@ class ProjectsConsoleClientTest extends Scope $data = array_merge($data, ['platformAppleWatchOsId' => $response['body']['$id']]); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2599,7 +2618,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2622,7 +2641,7 @@ class ProjectsConsoleClientTest extends Scope sleep(1); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2646,7 +2665,7 @@ class ProjectsConsoleClientTest extends Scope $platformWebId = $data['platformWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2662,7 +2681,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultteriOSId = $data['platformFultteriOSId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2678,7 +2697,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterAndroidId = $data['platformFultterAndroidId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2694,7 +2713,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterWebId = $data['platformFultterWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2710,7 +2729,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleIosId = $data['platformAppleIosId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2726,7 +2745,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleMacOsId = $data['platformAppleMacOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2742,7 +2761,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleWatchOsId = $data['platformAppleWatchOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2758,7 +2777,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleTvOsId = $data['platformAppleTvOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2775,7 +2794,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2794,7 +2813,7 @@ class ProjectsConsoleClientTest extends Scope $platformWebId = $data['platformWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2813,7 +2832,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultteriOSId = $data['platformFultteriOSId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2832,7 +2851,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterAndroidId = $data['platformFultterAndroidId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2851,7 +2870,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterWebId = $data['platformFultterWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2870,7 +2889,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleIosId = $data['platformAppleIosId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2889,7 +2908,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleMacOsId = $data['platformAppleMacOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2908,7 +2927,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleWatchOsId = $data['platformAppleWatchOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2927,7 +2946,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleTvOsId = $data['platformAppleTvOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2947,7 +2966,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/error', array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/platforms/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2969,7 +2988,7 @@ class ProjectsConsoleClientTest extends Scope $platformWebId = $data['platformWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2977,7 +2996,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2986,7 +3005,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultteriOSId = $data['platformFultteriOSId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -2994,7 +3013,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultteriOSId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultteriOSId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3003,7 +3022,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterAndroidId = $data['platformFultterAndroidId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3011,7 +3030,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterAndroidId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterAndroidId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3020,7 +3039,7 @@ class ProjectsConsoleClientTest extends Scope $platformFultterWebId = $data['platformFultterWebId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3028,7 +3047,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformFultterWebId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformFultterWebId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3037,7 +3056,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleIosId = $data['platformAppleIosId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3045,7 +3064,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleIosId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleIosId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3054,7 +3073,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleMacOsId = $data['platformAppleMacOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3062,7 +3081,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleMacOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleMacOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3071,7 +3090,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleWatchOsId = $data['platformAppleWatchOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3079,7 +3098,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleWatchOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3088,7 +3107,7 @@ class ProjectsConsoleClientTest extends Scope $platformAppleTvOsId = $data['platformAppleTvOsId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3096,7 +3115,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/platforms/'.$platformAppleTvOsId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/platforms/' . $platformAppleTvOsId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3106,7 +3125,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3125,7 +3144,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/domains', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/domains', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3145,7 +3164,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3154,13 +3173,13 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/platforms', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'type' => 'web', 'name' => 'Too Long Hostname', - 'hostname' => \str_repeat('bestdomain', 25).'.com', // 250 + 4 chars total (exactly above limit) + 'hostname' => \str_repeat("bestdomain", 25) . '.com' // 250 + 4 chars total (exactly above limit) ]); return $data; @@ -3173,7 +3192,7 @@ class ProjectsConsoleClientTest extends Scope { $id = $data['projectId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3196,7 +3215,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $domainId = $data['domainId'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains/'.$domainId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains/' . $domainId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3213,7 +3232,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3231,7 +3250,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $domainId = $data['domainId'] ?? ''; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/'.$id.'/domains/'.$domainId.'/verification', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/domains/' . $domainId . '/verification', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3253,7 +3272,7 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId'] ?? ''; $domainId = $data['domainId'] ?? ''; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/domains/'.$domainId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/domains/' . $domainId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3261,7 +3280,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/domains/'.$domainId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/domains/' . $domainId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3271,7 +3290,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/'.$id.'/domains/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/domains/error', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -3307,7 +3326,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Amazing Project', 'teamId' => $teamId, - 'region' => 'default', + 'region' => 'default' ]); $this->assertEquals(201, $project['headers']['status-code']); @@ -3318,14 +3337,14 @@ class ProjectsConsoleClientTest extends Scope $projectId = $project['body']['$id']; // Ensure I can get both team and project - $team = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId, array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $team['headers']['status-code']); - $project = $this->client->call(Client::METHOD_GET, '/projects/'.$projectId, array_merge([ + $project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3333,7 +3352,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $project['headers']['status-code']); // Delete Project - $project = $this->client->call(Client::METHOD_DELETE, '/projects/'.$projectId, array_merge([ + $project = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -3341,14 +3360,14 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(204, $project['headers']['status-code']); // Ensure I can get team but not a project - $team = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId, array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $team['headers']['status-code']); - $project = $this->client->call(Client::METHOD_GET, '/projects/'.$projectId, array_merge([ + $project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php index 25140309af..9dfd48ce50 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php @@ -2,9 +2,10 @@ namespace Tests\E2E\Services\Projects; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; +use Tests\E2E\Client; class ProjectsCustomClientTest extends Scope { diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index 436d1df611..1c5b48f146 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Projects; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Tests\E2E\Client; class ProjectsCustomServerTest extends Scope { diff --git a/tests/e2e/Services/Realtime/RealtimeBase.php b/tests/e2e/Services/Realtime/RealtimeBase.php index baf27e78ea..62bb7f5d3b 100644 --- a/tests/e2e/Services/Realtime/RealtimeBase.php +++ b/tests/e2e/Services/Realtime/RealtimeBase.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Realtime; -use WebSocket\Client as WebSocketClient; use WebSocket\ConnectionException; +use WebSocket\Client as WebSocketClient; trait RealtimeBase { @@ -14,15 +14,15 @@ trait RealtimeBase } $headers = array_merge([ - 'Origin' => 'appwrite.test', + 'Origin' => 'appwrite.test' ], $headers); $query = [ 'project' => $projectId, - 'channels' => $channels, + 'channels' => $channels ]; - return new WebSocketClient('ws://appwrite-traefik/v1/realtime?'.http_build_query($query), [ + return new WebSocketClient('ws://appwrite-traefik/v1/realtime?' . http_build_query($query), [ 'headers' => $headers, 'timeout' => 30, ]); @@ -57,8 +57,8 @@ trait RealtimeBase { $client = new WebSocketClient('ws://appwrite-traefik/v1/realtime?project=123', [ 'headers' => [ - 'Origin' => 'appwrite.test', - ], + 'Origin' => 'appwrite.test' + ] ]); $payload = json_decode($client->receive(), true); diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 363da4d611..3ef258885c 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -4,8 +4,8 @@ namespace Tests\E2E\Services\Realtime; use CURLFile; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideConsole; use Tests\E2E\Services\Functions\FunctionsBase; use Utopia\Database\Helpers\ID; @@ -29,7 +29,7 @@ class RealtimeConsoleClientTest extends Scope * Test for SUCCESS */ $client = $this->getWebsocket(['account'], [ - 'origin' => 'http://localhost', + 'origin' => 'http://localhost' ]); $response = json_decode($client->receive(), true); @@ -43,8 +43,8 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => $session, - ], + 'session' => $session + ] ])); $response = json_decode($client->receive(), true); @@ -64,8 +64,8 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => 'invalid_session', - ], + 'session' => 'invalid_session' + ] ])); $response = json_decode($client->receive(), true); @@ -79,7 +79,7 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', - 'data' => [], + 'data' => [] ])); $response = json_decode($client->receive(), true); @@ -94,8 +94,8 @@ class RealtimeConsoleClientTest extends Scope $client->send(\json_encode([ 'type' => 'unknown', 'data' => [ - 'session' => 'invalid_session', - ], + 'session' => 'invalid_session' + ] ])); $response = json_decode($client->receive(), true); @@ -120,6 +120,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertEquals(1003, $response['data']['code']); $this->assertEquals('Message format is not valid.', $response['data']['message']); + $client->close(); } @@ -130,7 +131,7 @@ class RealtimeConsoleClientTest extends Scope $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -158,7 +159,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Attributes */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -174,7 +175,7 @@ class RealtimeConsoleClientTest extends Scope $actorsId = $actors['body']['$id']; - $name = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ + $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -206,7 +207,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('processing', $response['data']['payload']['status']); @@ -226,7 +227,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('available', $response['data']['payload']['status']); @@ -247,7 +248,7 @@ class RealtimeConsoleClientTest extends Scope $databaseId = $data['databaseId']; $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -263,7 +264,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Indexes */ - $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -329,7 +330,7 @@ class RealtimeConsoleClientTest extends Scope $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -345,7 +346,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Delete Index */ - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/indexes/key_name', array_merge([ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/indexes/key_name', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -385,7 +386,7 @@ class RealtimeConsoleClientTest extends Scope $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -401,7 +402,7 @@ class RealtimeConsoleClientTest extends Scope /** * Test Delete Attribute */ - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/attributes/name', array_merge([ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/attributes/name', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -442,18 +443,19 @@ class RealtimeConsoleClientTest extends Scope 'users.*.delete', ], 'schedule' => '0 0 1 1 *', - 'timeout' => 10, + 'timeout' => 10 ]); $functionId = $response1['body']['$id'] ?? ''; $this->assertEquals(201, $response1['headers']['status-code']); + $projectId = 'console'; $client = $this->getWebsocket(['console'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='.$this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ], $projectId); $response = json_decode($client->receive(), true); @@ -469,17 +471,18 @@ class RealtimeConsoleClientTest extends Scope /** * Test Create Deployment */ + $folder = 'php'; - $code = realpath(__DIR__.'/../../../resources/functions')."/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 456bb7d333..4f880338a4 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -4,8 +4,8 @@ namespace Tests\E2E\Services\Realtime; use CURLFile; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\CLI\Console; use Utopia\Database\Helpers\ID; @@ -25,9 +25,9 @@ class RealtimeCustomClientTest extends Scope $userId = $user['$id'] ?? ''; $session = $user['session'] ?? ''; - $headers = [ + $headers = [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session ]; $client = $this->getWebsocket(['documents'], $headers); @@ -54,7 +54,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']['user']); $this->assertCount(2, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -70,7 +70,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(3, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -96,7 +96,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']['user']); $this->assertCount(10, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains('files', $response['data']['channels']); $this->assertContains('files.1', $response['data']['channels']); $this->assertContains('collections', $response['data']['channels']); @@ -120,7 +120,7 @@ class RealtimeCustomClientTest extends Scope * Test for SUCCESS */ $client = $this->getWebsocket(['account'], [ - 'origin' => 'http://localhost', + 'origin' => 'http://localhost' ]); $response = json_decode($client->receive(), true); @@ -134,8 +134,8 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => $session, - ], + 'session' => $session + ] ])); $response = json_decode($client->receive(), true); @@ -155,8 +155,8 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', 'data' => [ - 'session' => 'invalid_session', - ], + 'session' => 'invalid_session' + ] ])); $response = json_decode($client->receive(), true); @@ -170,7 +170,7 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'authentication', - 'data' => [], + 'data' => [] ])); $response = json_decode($client->receive(), true); @@ -185,8 +185,8 @@ class RealtimeCustomClientTest extends Scope $client->send(\json_encode([ 'type' => 'unknown', 'data' => [ - 'session' => 'invalid_session', - ], + 'session' => 'invalid_session' + ] ])); $response = json_decode($client->receive(), true); @@ -211,6 +211,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals(1003, $response['data']['code']); $this->assertEquals('Message format is not valid.', $response['data']['message']); + $client->close(); } @@ -241,7 +242,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['account'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -251,22 +252,22 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertNotEmpty($response['data']['user']); $this->assertEquals($userId, $response['data']['user']['$id']); /** * Test Account Name Event */ - $name = 'Torsten Dittmann'; + $name = "Torsten Dittmann"; $this->client->call(Client::METHOD_PATCH, '/account/name', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session, ]), [ - 'name' => $name, + 'name' => $name ]); $response = json_decode($client->receive(), true); @@ -278,17 +279,18 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.name", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains('users.*.update.name', $response['data']['events']); - $this->assertContains('users.*.update', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.update.name", $response['data']['events']); + $this->assertContains("users.*.update", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($name, $response['data']['payload']['name']); + /** * Test Account Password Event */ @@ -296,7 +298,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => 'password', @@ -311,13 +313,13 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.password", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains('users.*.update.password', $response['data']['events']); - $this->assertContains('users.*.update', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.update.password", $response['data']['events']); + $this->assertContains("users.*.update", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($name, $response['data']['payload']['name']); @@ -329,7 +331,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session, ]), [ 'email' => 'torsten@appwrite.io', 'password' => 'new-password', @@ -344,13 +346,13 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.email", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains('users.*.update.email', $response['data']['events']); - $this->assertContains('users.*.update', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.update.email", $response['data']['events']); + $this->assertContains("users.*.update", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('torsten@appwrite.io', $response['data']['payload']['email']); @@ -361,7 +363,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session, ]), [ 'url' => 'http://localhost/verification', ]); @@ -375,7 +377,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.verification.{$verificationId}.create", $response['data']['events']); $this->assertContains("users.{$userId}.verification.{$verificationId}", $response['data']['events']); $this->assertContains("users.{$userId}.verification.*.create", $response['data']['events']); @@ -383,9 +385,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}.create", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}", $response['data']['events']); - $this->assertContains('users.*.verification.*.create', $response['data']['events']); - $this->assertContains('users.*.verification.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.verification.*.create", $response['data']['events']); + $this->assertContains("users.*.verification.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $lastEmail = $this->getLastEmail(); $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); @@ -397,7 +399,7 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session, ]), [ 'userId' => $userId, 'secret' => $verification, @@ -412,7 +414,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.verification.{$verificationId}.update", $response['data']['events']); $this->assertContains("users.{$userId}.verification.{$verificationId}", $response['data']['events']); $this->assertContains("users.{$userId}.verification.*.update", $response['data']['events']); @@ -420,9 +422,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}.update", $response['data']['events']); $this->assertContains("users.*.verification.{$verificationId}", $response['data']['events']); - $this->assertContains('users.*.verification.*.update', $response['data']['events']); - $this->assertContains('users.*.verification.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.verification.*.update", $response['data']['events']); + $this->assertContains("users.*.verification.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); /** * Test Acoount Prefs Update */ @@ -430,12 +432,12 @@ class RealtimeCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ], + ] ]); $response = json_decode($client->receive(), true); @@ -447,13 +449,13 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.update.prefs", $response['data']['events']); $this->assertContains("users.{$userId}.update", $response['data']['events']); $this->assertContains("users.{$userId}", $response['data']['events']); - $this->assertContains('users.*.update.prefs', $response['data']['events']); - $this->assertContains('users.*.update', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.update.prefs", $response['data']['events']); + $this->assertContains("users.*.update", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $createSession = function () use ($projectId): array { @@ -466,10 +468,10 @@ class RealtimeCustomClientTest extends Scope 'password' => 'new-password', ]); - $sessionNew = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$projectId]; + $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $projectId]; $sessionNewId = $response['body']['$id']; - return ['session' => $sessionNew, 'sessionId' => $sessionNewId]; + return array("session" => $sessionNew, "sessionId" => $sessionNewId); }; /** @@ -488,7 +490,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}.create", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.*.create", $response['data']['events']); @@ -496,19 +498,19 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}.create", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']); - $this->assertContains('users.*.sessions.*.create', $response['data']['events']); - $this->assertContains('users.*.sessions.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.sessions.*.create", $response['data']['events']); + $this->assertContains("users.*.sessions.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test Account Session Delete */ - $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionNewId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - 'cookie' => 'a_session_'.$projectId.'='.$sessionNew, + 'cookie' => 'a_session_' . $projectId . '=' . $sessionNew, ])); $response = json_decode($client->receive(), true); @@ -520,7 +522,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.*.delete", $response['data']['events']); @@ -528,20 +530,21 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']); - $this->assertContains('users.*.sessions.*.delete', $response['data']['events']); - $this->assertContains('users.*.sessions.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.sessions.*.delete", $response['data']['events']); + $this->assertContains("users.*.sessions.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test User Account Session Delete */ + $sessionData = $createSession(); $sessionNew = $sessionData['session']; $sessionNewId = $sessionData['sessionId']; $client->receive(); // Receive the creation message and drop; this was tested earlier already - $this->client->call(Client::METHOD_DELETE, '/users/'.$userId.'/sessions/'.$sessionNewId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/users/' . $userId . '/sessions/' . $sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, @@ -556,7 +559,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.{$sessionNewId}", $response['data']['events']); $this->assertContains("users.{$userId}.sessions.*.delete", $response['data']['events']); @@ -564,9 +567,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}.delete", $response['data']['events']); $this->assertContains("users.*.sessions.{$sessionNewId}", $response['data']['events']); - $this->assertContains('users.*.sessions.*.delete', $response['data']['events']); - $this->assertContains('users.*.sessions.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.sessions.*.delete", $response['data']['events']); + $this->assertContains("users.*.sessions.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** @@ -593,7 +596,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}.create", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.*.create", $response['data']['events']); @@ -601,9 +604,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}.create", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}", $response['data']['events']); - $this->assertContains('users.*.recovery.*.create', $response['data']['events']); - $this->assertContains('users.*.recovery.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.recovery.*.create", $response['data']['events']); + $this->assertContains("users.*.recovery.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $response = $this->client->call(Client::METHOD_PUT, '/account/recovery', array_merge([ @@ -626,7 +629,7 @@ class RealtimeCustomClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertContains('account', $response['data']['channels']); - $this->assertContains('account.'.$userId, $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}.update", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.{$recoveryId}", $response['data']['events']); $this->assertContains("users.{$userId}.recovery.*.update", $response['data']['events']); @@ -634,9 +637,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.{$userId}", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}.update", $response['data']['events']); $this->assertContains("users.*.recovery.{$recoveryId}", $response['data']['events']); - $this->assertContains('users.*.recovery.*.update', $response['data']['events']); - $this->assertContains('users.*.recovery.*', $response['data']['events']); - $this->assertContains('users.*', $response['data']['events']); + $this->assertContains("users.*.recovery.*.update", $response['data']['events']); + $this->assertContains("users.*.recovery.*", $response['data']['events']); + $this->assertContains("users.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); @@ -650,7 +653,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['documents', 'collections'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -671,7 +674,7 @@ class RealtimeCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'Actors DB', @@ -682,10 +685,10 @@ class RealtimeCustomClientTest extends Scope /** * Test Collection Create */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -697,10 +700,10 @@ class RealtimeCustomClientTest extends Scope $actorsId = $actors['body']['$id']; - $name = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ + $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 256, @@ -718,13 +721,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Create */ - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Chris Evans', + 'name' => 'Chris Evans' ], 'permissions' => [ Permission::read(Role::any()), @@ -744,8 +747,8 @@ class RealtimeCustomClientTest extends Scope $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); - $this->assertContains('databases.'.$databaseId.'.collections.'.$actorsId.'.documents.'.$documentId, $response['data']['channels']); - $this->assertContains('databases.'.$databaseId.'.collections.'.$actorsId.'.documents', $response['data']['channels']); + $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents.' . $documentId, $response['data']['channels']); + $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $response['data']['events']); @@ -757,20 +760,20 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans'); /** * Test Document Update */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Chris Evans 2', + 'name' => 'Chris Evans 2' ], 'permissions' => [ Permission::read(Role::any()), @@ -801,7 +804,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2'); @@ -809,13 +812,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Delete */ - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Bradley Cooper', + 'name' => 'Bradley Cooper' ], 'permissions' => [ Permission::read(Role::any()), @@ -828,7 +831,7 @@ class RealtimeCustomClientTest extends Scope $documentId = $document['body']['$id']; - $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -855,7 +858,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper'); @@ -870,7 +873,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['documents', 'collections'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -891,7 +894,7 @@ class RealtimeCustomClientTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), 'name' => 'Actors DB', @@ -902,10 +905,10 @@ class RealtimeCustomClientTest extends Scope /** * Test Collection Create */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -914,15 +917,15 @@ class RealtimeCustomClientTest extends Scope Permission::create(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), - ], + ] ]); $actorsId = $actors['body']['$id']; - $name = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ + $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'name', 'size' => 256, @@ -940,13 +943,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Create */ - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Chris Evans', + 'name' => 'Chris Evans' ], 'permissions' => [], ]); @@ -975,19 +978,19 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans'); /** * Test Document Update */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'data' => [ - 'name' => 'Chris Evans 2', + 'name' => 'Chris Evans 2' ], 'permissions' => [], ]); @@ -1014,7 +1017,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2'); @@ -1022,13 +1025,13 @@ class RealtimeCustomClientTest extends Scope /** * Test Document Delete */ - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => ID::unique(), 'data' => [ - 'name' => 'Bradley Cooper', + 'name' => 'Bradley Cooper' ], 'permissions' => [], ]); @@ -1037,7 +1040,7 @@ class RealtimeCustomClientTest extends Scope $client->receive(); - $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$documentId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1064,7 +1067,7 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); - $this->assertContains('databases.*', $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper'); @@ -1079,7 +1082,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['files'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -1098,7 +1101,7 @@ class RealtimeCustomClientTest extends Scope $bucket1 = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'bucketId' => ID::unique(), 'name' => 'Bucket 1', @@ -1107,7 +1110,7 @@ class RealtimeCustomClientTest extends Scope Permission::create(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), - ], + ] ]); $bucketId = $bucket1['body']['$id']; @@ -1115,12 +1118,12 @@ class RealtimeCustomClientTest extends Scope /** * Test File Create */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -1148,9 +1151,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("buckets.{$bucketId}", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}.create", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']); - $this->assertContains('buckets.*.files.*.create', $response['data']['events']); - $this->assertContains('buckets.*.files.*', $response['data']['events']); - $this->assertContains('buckets.*', $response['data']['events']); + $this->assertContains("buckets.*.files.*.create", $response['data']['events']); + $this->assertContains("buckets.*.files.*", $response['data']['events']); + $this->assertContains("buckets.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $fileId = $file['body']['$id']; @@ -1158,7 +1161,7 @@ class RealtimeCustomClientTest extends Scope /** * Test File Update */ - $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1187,15 +1190,15 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("buckets.{$bucketId}", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}.update", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']); - $this->assertContains('buckets.*.files.*.update', $response['data']['events']); - $this->assertContains('buckets.*.files.*', $response['data']['events']); - $this->assertContains('buckets.*', $response['data']['events']); + $this->assertContains("buckets.*.files.*.update", $response['data']['events']); + $this->assertContains("buckets.*.files.*", $response['data']['events']); + $this->assertContains("buckets.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test File Delete */ - $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1218,9 +1221,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("buckets.{$bucketId}", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}.delete", $response['data']['events']); $this->assertContains("buckets.*.files.{$fileId}", $response['data']['events']); - $this->assertContains('buckets.*.files.*.delete', $response['data']['events']); - $this->assertContains('buckets.*.files.*', $response['data']['events']); - $this->assertContains('buckets.*', $response['data']['events']); + $this->assertContains("buckets.*.files.*.delete", $response['data']['events']); + $this->assertContains("buckets.*.files.*", $response['data']['events']); + $this->assertContains("buckets.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); @@ -1234,7 +1237,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['executions'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -1254,7 +1257,7 @@ class RealtimeCustomClientTest extends Scope $function = $this->client->call(Client::METHOD_POST, '/functions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'functionId' => ID::unique(), 'name' => 'Test', @@ -1271,18 +1274,18 @@ class RealtimeCustomClientTest extends Scope $folder = 'timeout'; $stderr = ''; $stdout = ''; - $code = realpath(__DIR__.'/../../../resources/functions')."/{$folder}/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz"; - Console::execute('cd '.realpath(__DIR__.'/../../../resources/functions')."/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); + Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), - 'activate' => true, + 'activate' => true ]); $deploymentId = $deployment['body']['$id'] ?? ''; @@ -1293,20 +1296,20 @@ class RealtimeCustomClientTest extends Scope // Wait for deployment to be built. sleep(10); - $response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']['$id']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'async' => true, + 'async' => true ]); $this->assertEquals($execution['headers']['status-code'], 202); @@ -1334,9 +1337,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("functions.{$functionId}", $response['data']['events']); $this->assertContains("functions.*.executions.{$executionId}.create", $response['data']['events']); $this->assertContains("functions.*.executions.{$executionId}", $response['data']['events']); - $this->assertContains('functions.*.executions.*.create', $response['data']['events']); - $this->assertContains('functions.*.executions.*', $response['data']['events']); - $this->assertContains('functions.*', $response['data']['events']); + $this->assertContains("functions.*.executions.*.create", $response['data']['events']); + $this->assertContains("functions.*.executions.*", $response['data']['events']); + $this->assertContains("functions.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertArrayHasKey('type', $responseUpdate); @@ -1356,15 +1359,15 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("functions.{$functionId}", $responseUpdate['data']['events']); $this->assertContains("functions.*.executions.{$executionId}.update", $responseUpdate['data']['events']); $this->assertContains("functions.*.executions.{$executionId}", $responseUpdate['data']['events']); - $this->assertContains('functions.*.executions.*.update', $responseUpdate['data']['events']); - $this->assertContains('functions.*.executions.*', $responseUpdate['data']['events']); - $this->assertContains('functions.*', $responseUpdate['data']['events']); + $this->assertContains("functions.*.executions.*.update", $responseUpdate['data']['events']); + $this->assertContains("functions.*.executions.*", $responseUpdate['data']['events']); + $this->assertContains("functions.*", $responseUpdate['data']['events']); $this->assertNotEmpty($responseUpdate['data']['payload']); $client->close(); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1381,7 +1384,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['teams'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -1403,7 +1406,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal', + 'name' => 'Arsenal' ]); $teamId = $team['body']['$id'] ?? ''; @@ -1423,18 +1426,18 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}", $response['data']['channels']); $this->assertContains("teams.{$teamId}.create", $response['data']['events']); $this->assertContains("teams.{$teamId}", $response['data']['events']); - $this->assertContains('teams.*.create', $response['data']['events']); - $this->assertContains('teams.*', $response['data']['events']); + $this->assertContains("teams.*.create", $response['data']['events']); + $this->assertContains("teams.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test Team Update */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId, array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ - 'name' => 'Manchester', + 'name' => 'Manchester' ]); $this->assertEquals($team['headers']['status-code'], 200); @@ -1452,21 +1455,21 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}", $response['data']['channels']); $this->assertContains("teams.{$teamId}.update", $response['data']['events']); $this->assertContains("teams.{$teamId}", $response['data']['events']); - $this->assertContains('teams.*.update', $response['data']['events']); - $this->assertContains('teams.*', $response['data']['events']); + $this->assertContains("teams.*.update", $response['data']['events']); + $this->assertContains("teams.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** * Test Team Update Prefs */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId.'/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'prefs' => [ 'funcKey1' => 'funcValue1', 'funcKey2' => 'funcValue2', - ], + ] ]); $this->assertEquals($team['headers']['status-code'], 200); @@ -1486,9 +1489,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}.update", $response['data']['events']); $this->assertContains("teams.{$teamId}.update.prefs", $response['data']['events']); $this->assertContains("teams.{$teamId}", $response['data']['events']); - $this->assertContains('teams.*.update.prefs', $response['data']['events']); - $this->assertContains('teams.*.update', $response['data']['events']); - $this->assertContains('teams.*', $response['data']['events']); + $this->assertContains("teams.*.update.prefs", $response['data']['events']); + $this->assertContains("teams.*.update", $response['data']['events']); + $this->assertContains("teams.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals($response['data']['payload']['funcKey1'], 'funcValue1'); $this->assertEquals($response['data']['payload']['funcKey2'], 'funcValue2'); @@ -1511,7 +1514,7 @@ class RealtimeCustomClientTest extends Scope $client = $this->getWebsocket(['memberships'], [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$projectId.'='.$session, + 'cookie' => 'a_session_' . $projectId . '=' . $session ]); $response = json_decode($client->receive(), true); @@ -1525,7 +1528,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']['user']); $this->assertEquals($user['$id'], $response['data']['user']['$id']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1536,12 +1539,12 @@ class RealtimeCustomClientTest extends Scope * Test Update Membership */ $roles = ['admin', 'editor', 'uncle']; - $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamId.'/memberships/'.$membershipId, array_merge([ + $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamId . '/memberships/' . $membershipId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles, + 'roles' => $roles ]); $response = json_decode($client->receive(), true); @@ -1561,9 +1564,9 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.{$teamId}", $response['data']['events']); $this->assertContains("teams.*.memberships.{$membershipId}.update", $response['data']['events']); $this->assertContains("teams.*.memberships.{$membershipId}", $response['data']['events']); - $this->assertContains('teams.*.memberships.*.update', $response['data']['events']); - $this->assertContains('teams.*.memberships.*', $response['data']['events']); - $this->assertContains('teams.*', $response['data']['events']); + $this->assertContains("teams.*.memberships.*.update", $response['data']['events']); + $this->assertContains("teams.*.memberships.*", $response['data']['events']); + $this->assertContains("teams.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 9b0a6449d3..b19fe49ed0 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Storage; use CURLFile; use Tests\E2E\Client; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -25,7 +26,7 @@ trait StorageBase 'name' => 'Test Bucket', 'fileSecurity' => true, 'maximumFileSize' => 2000000, //2MB - 'allowedFileExtensions' => ['jpg', 'png'], + 'allowedFileExtensions' => ["jpg", "png"], 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -38,12 +39,12 @@ trait StorageBase $bucketId = $bucket['body']['$id']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -57,7 +58,7 @@ trait StorageBase $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $this->assertTrue(md5_file(realpath(__DIR__.'/../../../resources/logo.png')) == $file['body']['signature']); + $this->assertTrue(md5_file(realpath(__DIR__ . '/../../../resources/logo.png')) == $file['body']['signature']); /** * Test for Large File above 20MB * This should also validate the test for when Bucket encryption @@ -84,26 +85,27 @@ trait StorageBase /** * Chunked Upload */ - $source = __DIR__.'/../../../resources/disk-a/large-file.mp4'; + + $source = __DIR__ . "/../../../resources/disk-a/large-file.mp4"; $totalSize = \filesize($source); $chunkSize = 5 * 1024 * 1024; - $handle = @fopen($source, 'rb'); + $handle = @fopen($source, "rb"); $fileId = 'unique()'; $mimeType = mime_content_type($source); $counter = 0; $size = filesize($source); $headers = [ 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ]; $id = ''; - while (! feof($handle)) { - $curlFile = new \CURLFile('data://'.$mimeType.';base64,'.base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); - $headers['content-range'] = 'bytes '.($counter * $chunkSize).'-'.min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1).'/'.$size; - if (! empty($id)) { + while (!feof($handle)) { + $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); + $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; + if (!empty($id)) { $headers['x-appwrite-id'] = $id; } - $largeFile = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucket2['body']['$id'].'/files', array_merge($headers, $this->getHeaders()), [ + $largeFile = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', array_merge($headers, $this->getHeaders()), [ 'fileId' => $fileId, 'file' => $curlFile, 'permissions' => [ @@ -123,28 +125,28 @@ trait StorageBase $this->assertEquals('large-file.mp4', $largeFile['body']['name']); $this->assertEquals('video/mp4', $largeFile['body']['mimeType']); $this->assertEquals($totalSize, $largeFile['body']['sizeOriginal']); - $this->assertEquals(md5_file(realpath(__DIR__.'/../../../resources/disk-a/large-file.mp4')), $largeFile['body']['signature']); // should validate that the file is not encrypted + $this->assertEquals(md5_file(realpath(__DIR__ . '/../../../resources/disk-a/large-file.mp4')), $largeFile['body']['signature']); // should validate that the file is not encrypted /** * Failure * Test for Chunk above 5MB */ - $source = __DIR__.'/../../../resources/disk-a/large-file.mp4'; + $source = __DIR__ . "/../../../resources/disk-a/large-file.mp4"; $totalSize = \filesize($source); $chunkSize = 6 * 1024 * 1024; - $handle = @fopen($source, 'rb'); + $handle = @fopen($source, "rb"); $fileId = 'unique()'; $mimeType = mime_content_type($source); $counter = 0; $size = filesize($source); $headers = [ 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ]; $id = ''; - $curlFile = new \CURLFile('data://'.$mimeType.';base64,'.base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); - $headers['content-range'] = 'bytes '.($counter * $chunkSize).'-'.min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1).'/'.$size; - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucket2['body']['$id'].'/files', $this->getHeaders(), [ + $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); + $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', $this->getHeaders(), [ 'fileId' => $fileId, 'file' => $curlFile, 'permissions' => [ @@ -157,15 +159,17 @@ trait StorageBase $this->assertEquals(413, $res['headers']['status-code']); + /** * Test for FAILURE unknown Bucket */ + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/empty/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -177,12 +181,13 @@ trait StorageBase /** * Test for FAILURE file above bucket's file size limit */ - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/disk-b/kitten-1.png'), 'image/png', 'kitten-1.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-b/kitten-1.png'), 'image/png', 'kitten-1.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -196,12 +201,13 @@ trait StorageBase /** * Test for FAILURE unsupported bucket file extension */ - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/disk-a/kitten-3.gif'), 'image/gif', 'kitten-3.gif'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-a/kitten-3.gif'), 'image/gif', 'kitten-3.gif'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -224,7 +230,7 @@ trait StorageBase 'name' => 'Test Bucket 2', 'fileSecurity' => true, 'maximumFileSize' => 200000000, //200MB - 'allowedFileExtensions' => ['jpg', 'png'], + 'allowedFileExtensions' => ["jpg", "png"], 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -238,12 +244,12 @@ trait StorageBase /** * Test for FAILURE set x-appwrite-id to unique() */ - $source = realpath(__DIR__.'/../../../resources/logo.png'); + $source = realpath(__DIR__ . '/../../../resources/logo.png'); $totalSize = \filesize($source); - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'content-range' => 'bytes 0-'.$size.'/'.$size, + 'content-range' => 'bytes 0-' . $size . '/' . $size, 'x-appwrite-id' => 'unique()', ], $this->getHeaders()), [ 'fileId' => ID::unique(), @@ -272,7 +278,7 @@ trait StorageBase 'name' => 'Test Bucket', 'fileSecurity' => true, 'maximumFileSize' => 2000000, //2MB - 'allowedFileExtensions' => ['jpg', 'png'], + 'allowedFileExtensions' => ["jpg", "png"], 'compression' => 'zstd', 'permissions' => [ Permission::read(Role::any()), @@ -287,12 +293,12 @@ trait StorageBase $bucketId = $bucket['body']['$id']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -305,7 +311,7 @@ trait StorageBase $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $this->assertTrue(md5_file(realpath(__DIR__.'/../../../resources/logo.png')) == $file['body']['signature']); + $this->assertTrue(md5_file(realpath(__DIR__ . '/../../../resources/logo.png')) == $file['body']['signature']); return ['bucketId' => $bucketId]; } @@ -318,7 +324,7 @@ trait StorageBase /** * Test for SUCCESS */ - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -326,38 +332,38 @@ trait StorageBase $this->assertGreaterThan(0, $files['body']['total']); $this->assertGreaterThan(0, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(1, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(0, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("mimeType", "image/png")'], + 'queries' => [ 'equal("mimeType", "image/png")' ] ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(1, count($files['body']['files'])); - $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("mimeType", "image/jpeg")'], + 'queries' => [ 'equal("mimeType", "image/jpeg")' ] ]); $this->assertEquals(200, $files['headers']['status-code']); $this->assertEquals(0, count($files['body']['files'])); @@ -365,6 +371,7 @@ trait StorageBase /** * Test for FAILURE unknown Bucket */ + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -383,7 +390,7 @@ trait StorageBase /** * Test for SUCCESS */ - $file1 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'], array_merge([ + $file1 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -397,7 +404,7 @@ trait StorageBase $this->assertIsArray($file1['body']['$permissions']); $this->assertCount(3, $file1['body']['$permissions']); - $file2 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ + $file2 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -407,7 +414,7 @@ trait StorageBase $this->assertNotEmpty($file2['body']); //new image preview features - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -425,13 +432,13 @@ trait StorageBase $image = new \Imagick(); $image->readImageBlob($file3['body']); - $original = new \Imagick(__DIR__.'/../../../resources/logo-after.png'); + $original = new \Imagick(__DIR__ . '/../../../resources/logo-after.png'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); $this->assertEquals('PNG', $image->getImageFormat()); - $file4 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ + $file4 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -448,13 +455,13 @@ trait StorageBase $image = new \Imagick(); $image->readImageBlob($file4['body']); - $original = new \Imagick(__DIR__.'/../../../resources/logo-after.jpg'); + $original = new \Imagick(__DIR__ . '/../../../resources/logo-after.jpg'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); $this->assertEquals('JPEG', $image->getImageFormat()); - $file5 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ + $file5 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -465,13 +472,13 @@ trait StorageBase $this->assertNotEmpty($file5['body']); // Test ranged download - $file51 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ + $file51 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=0-99', ], $this->getHeaders())); - $path = __DIR__.'/../../../resources/logo.png'; + $path = __DIR__ . '/../../../resources/logo.png'; $originalChunk = \file_get_contents($path, false, null, 0, 100); $this->assertEquals(206, $file51['headers']['status-code']); @@ -481,7 +488,7 @@ trait StorageBase $this->assertEquals($originalChunk, $file51['body']); // Test ranged download - with invalid range - $file52 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ + $file52 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=0-', @@ -490,7 +497,7 @@ trait StorageBase $this->assertEquals(206, $file52['headers']['status-code']); // Test ranged download - with invalid range - $file53 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ + $file53 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=988', @@ -499,7 +506,7 @@ trait StorageBase $this->assertEquals(416, $file53['headers']['status-code']); // Test ranged download - with invalid range - $file54 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/download', array_merge([ + $file54 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=-988', @@ -507,7 +514,7 @@ trait StorageBase $this->assertEquals(416, $file54['headers']['status-code']); - $file6 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/view', array_merge([ + $file6 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -517,7 +524,7 @@ trait StorageBase $this->assertNotEmpty($file6['body']); // Test for negative angle values in fileGetPreview - $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$data['fileId'].'/preview', array_merge([ + $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -535,7 +542,7 @@ trait StorageBase $image = new \Imagick(); $image->readImageBlob($file7['body']); - $original = new \Imagick(__DIR__.'/../../../resources/logo-after.png'); + $original = new \Imagick(__DIR__ . '/../../../resources/logo-after.png'); $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); @@ -544,7 +551,7 @@ trait StorageBase /** * Test large files decompress successfully */ - $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$data['largeBucketId'].'/files/'.$data['largeFileId'].'/download', array_merge([ + $file7 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['largeBucketId'] . '/files/' . $data['largeFileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -553,16 +560,17 @@ trait StorageBase $this->assertEquals('attachment; filename="large-file.mp4"', $file7['headers']['content-disposition']); $this->assertEquals('video/mp4', $file7['headers']['content-type']); $this->assertNotEmpty($fileData); - $this->assertEquals(md5_file(realpath(__DIR__.'/../../../resources/disk-a/large-file.mp4')), md5($fileData)); // validate the file is downloaded correctly + $this->assertEquals(md5_file(realpath(__DIR__ . '/../../../resources/disk-a/large-file.mp4')), md5($fileData)); // validate the file is downloaded correctly /** * Test for FAILURE unknown Bucket */ - $file8 = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty/files/'.$data['fileId'], array_merge([ + + $file8 = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 2, + 'limit' => 2 ]); $this->assertEquals(404, $file8['headers']['status-code']); @@ -577,12 +585,12 @@ trait StorageBase { $bucketId = $data['bucketId']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::custom('testcache'), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -595,7 +603,7 @@ trait StorageBase $fileId = $file['body']['$id']; //get image preview - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -614,7 +622,7 @@ trait StorageBase $imageBefore = new \Imagick(); $imageBefore->readImageBlob($file3['body']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$data['bucketId'].'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -623,12 +631,12 @@ trait StorageBase $this->assertEmpty($file['body']); sleep(1); //upload again using the same ID - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::custom('testcache'), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/disk-b/kitten-2.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-b/kitten-2.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -639,7 +647,7 @@ trait StorageBase $this->assertNotEmpty($file['body']['$id']); //get image preview after - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -670,12 +678,12 @@ trait StorageBase { $bucketId = $data['bucketId']; - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -688,7 +696,7 @@ trait StorageBase $fileId = $file['body']['$id']; //get image preview - $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -715,7 +723,7 @@ trait StorageBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -724,7 +732,7 @@ trait StorageBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -746,7 +754,8 @@ trait StorageBase /** * Test for FAILURE unknown Bucket */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/empty/files/'.$data['fileId'], array_merge([ + + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/empty/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -754,7 +763,7 @@ trait StorageBase Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals(404, $file['headers']['status-code']); @@ -770,7 +779,7 @@ trait StorageBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -778,7 +787,7 @@ trait StorageBase $this->assertEquals(204, $file['headers']['status-code']); $this->assertEmpty($file['body']); - $file = $this->client->call(Client::METHOD_GET, '/storage/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index 2d473c5c73..aff055f18d 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Storage; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideConsole; use Utopia\Database\Helpers\ID; @@ -21,9 +21,9 @@ class StorageConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_GET, '/storage/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '32h', + 'range' => '32h' ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -33,9 +33,9 @@ class StorageConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_GET, '/storage/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -55,7 +55,7 @@ class StorageConsoleClientTest extends Scope ], $this->getHeaders()), [ 'bucketId' => ID::unique(), 'name' => 'Test Bucket', - 'permission' => 'file', + 'permission' => 'file' ]); $this->assertEquals(201, $bucket['headers']['status-code']); $bucketId = $bucket['body']['$id']; @@ -63,11 +63,12 @@ class StorageConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/storage/'.$bucketId.'/usage', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/storage/' . $bucketId . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '32h', + 'range' => '32h' ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -76,9 +77,9 @@ class StorageConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_GET, '/storage/randomBucketId/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals($response['headers']['status-code'], 404); @@ -86,11 +87,11 @@ class StorageConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/storage/'.$bucketId.'/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/storage/' . $bucketId . '/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'range' => '24h', + 'range' => '24h' ]); $this->assertEquals($response['headers']['status-code'], 200); diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index f9ca64644a..12fc006968 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -4,9 +4,10 @@ namespace Tests\E2E\Services\Storage; use CURLFile; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -45,13 +46,13 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -62,14 +63,14 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -82,14 +83,14 @@ class StorageCustomClientTest extends Scope $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -100,14 +101,14 @@ class StorageCustomClientTest extends Scope $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -119,34 +120,35 @@ class StorageCustomClientTest extends Scope public function testBucketAnyPermissions(): void { + /** * Test for SUCCESS */ $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'bucketId' => ID::unique(), - 'name' => 'Test Bucket', - 'permissions' => [ - Permission::read(Role::any()), - Permission::create(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ - 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -157,46 +159,46 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'name' => 'permissions.png', + 'name' => 'permissions.png', ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(204, $file['headers']['status-code']); @@ -227,12 +229,12 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -243,35 +245,35 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -283,24 +285,24 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -309,7 +311,7 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -319,7 +321,7 @@ class StorageCustomClientTest extends Scope /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -352,12 +354,12 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -368,35 +370,35 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -408,22 +410,22 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); - $this->client->call(CLient::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $this->client->call(CLient::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -434,50 +436,50 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals($file['headers']['status-code'], 401); - $email = ID::unique().'@localhost.test'; + $email = ID::unique() . '@localhost.test'; $password = 'password'; $user2 = $this->createUser('user2', $email, $password); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'permissions' => [], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -485,11 +487,12 @@ class StorageCustomClientTest extends Scope /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); + $this->assertEquals(204, $file['headers']['status-code']); $this->assertEmpty($file['body']); } @@ -498,8 +501,8 @@ class StorageCustomClientTest extends Scope { $team1 = $this->createTeam(ID::unique(), 'Team 1'); $team2 = $this->createTeam(ID::unique(), 'Team 1'); - $user1 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); - $user2 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); + $user1 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); + $user2 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); $this->addToTeam($user1['$id'], $team1['$id']); $this->addToTeam($user2['$id'], $team2['$id']); @@ -528,13 +531,13 @@ class StorageCustomClientTest extends Scope $this->assertNotEmpty($bucketId); // Team 1 create success - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $fileId = $file['body']['$id']; @@ -546,73 +549,73 @@ class StorageCustomClientTest extends Scope $this->assertEquals(47218, $file['body']['sizeOriginal']); // Team 1 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -622,22 +625,22 @@ class StorageCustomClientTest extends Scope */ // Team 2 create failure - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); // Team 2 update failure - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'permissions' => [], ]); @@ -645,10 +648,10 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); // Team 2 delete failure - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -657,10 +660,10 @@ class StorageCustomClientTest extends Scope * Test for SUCCESS */ // Team 1 delete success - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(204, $file['headers']['status-code']); @@ -680,20 +683,20 @@ class StorageCustomClientTest extends Scope 'bucketId' => ID::unique(), 'name' => 'Test Bucket', 'permissions' => [], - 'fileSecurity' => true, + 'fileSecurity' => true ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::any()), ], @@ -707,28 +710,28 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -738,17 +741,17 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -769,20 +772,20 @@ class StorageCustomClientTest extends Scope 'bucketId' => ID::unique(), 'name' => 'Test Bucket', 'permissions' => [], - 'fileSecurity' => true, + 'fileSecurity' => true ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::users()), ], @@ -796,28 +799,28 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -827,17 +830,17 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -858,20 +861,20 @@ class StorageCustomClientTest extends Scope 'bucketId' => ID::unique(), 'name' => 'Test Bucket', 'permissions' => [], - 'fileSecurity' => true, + 'fileSecurity' => true ]); $bucketId = $bucket['body']['$id']; $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), ], @@ -885,28 +888,28 @@ class StorageCustomClientTest extends Scope $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', array_merge([ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -916,58 +919,58 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals(401, $file['headers']['status-code']); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(401, $file['headers']['status-code']); - $user2 = $this->createUser(ID::unique(), uniqid().'@localhost.test', 'password'); + $user2 = $this->createUser(ID::unique(), uniqid() . '@localhost.test', 'password'); - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 404); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'permissions' => [], ]); $this->assertEquals($file['headers']['status-code'], 401); - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -977,8 +980,8 @@ class StorageCustomClientTest extends Scope { $team1 = $this->createTeam(ID::unique(), 'Team 1'); $team2 = $this->createTeam(ID::unique(), 'Team 1'); - $user1 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); - $user2 = $this->createUser(ID::unique(), ID::unique().'@localhost.test', 'password'); + $user1 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); + $user2 = $this->createUser(ID::unique(), ID::unique() . '@localhost.test', 'password'); $this->addToTeam($user1['$id'], $team1['$id']); $this->addToTeam($user2['$id'], $team2['$id']); @@ -1001,13 +1004,13 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::read(Role::team(ID::custom($team1['$id']))), Permission::read(Role::team(ID::custom($team2['$id']))), @@ -1025,73 +1028,73 @@ class StorageCustomClientTest extends Scope $this->assertEquals(47218, $file['body']['sizeOriginal']); // Team 1 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 read success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 preview success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/preview', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 2 download success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/download', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); // Team 1 view success - $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/'.$bucketId.'/files/'.$fileId.'/view', [ + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -1101,32 +1104,32 @@ class StorageCustomClientTest extends Scope */ // Team 1 create failure - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); // Team 2 create failure - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 401); // Team 2 update failure - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ], [ 'permissions' => [], ]); @@ -1134,10 +1137,10 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 401); // Team 2 delete failure - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user2['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], ]); $this->assertEquals($file['headers']['status-code'], 401); @@ -1146,10 +1149,10 @@ class StorageCustomClientTest extends Scope * Test for SUCCESS */ // Team 1 delete success - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId.'/files/'.$fileId, [ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$user1['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], ]); $this->assertEquals(204, $file['headers']['status-code']); @@ -1184,15 +1187,15 @@ class StorageCustomClientTest extends Scope $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $bucket['body']['$permissions']); // File aliases write to update, delete - $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', array_merge([ + $file1 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::write(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertNotContains(Permission::create(Role::user($this->getUser()['$id'])), $file1['body']['$permissions']); @@ -1204,15 +1207,15 @@ class StorageCustomClientTest extends Scope */ // File does not allow create permission - $file2 = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucketId.'/files', [ + $file2 = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), - ], + ] ]); $this->assertEquals(400, $file2['headers']['status-code']); @@ -1241,12 +1244,12 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$bucket['body']['$id'].'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket['body']['$id'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), ]); $this->assertEquals($file['headers']['status-code'], 201); @@ -1270,12 +1273,12 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'folderId' => ID::custom('xyz'), 'permissions' => [ Permission::read(Role::user(ID::custom('notme'))), @@ -1286,33 +1289,33 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'folderId' => ID::custom('xyz'), 'permissions' => [ Permission::update(Role::user(ID::custom('notme'))), Permission::delete(Role::user(ID::custom('notme'))), - ], + ] ]); $this->assertEquals(401, $file['headers']['status-code']); $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'permissions.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'folderId' => ID::custom('xyz'), 'permissions' => [ Permission::read(Role::user(ID::custom('notme'))), @@ -1325,7 +1328,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); } /** @@ -1336,7 +1339,7 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1349,25 +1352,25 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'permissions' => [ Permission::update(Role::user(ID::custom('notme'))), Permission::delete(Role::user(ID::custom('notme'))), - ], + ] ]); $this->assertEquals(401, $file['headers']['status-code']); $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1382,6 +1385,6 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('any', $file['body']['message']); $this->assertStringContainsString('users', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); } } diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 2da95f7983..38fb0e0b9d 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -83,8 +83,8 @@ class StorageCustomServerTest extends Scope '/storage/buckets', array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -98,7 +98,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -108,7 +108,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -118,7 +118,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("$id", "bucket1")'], + 'queries' => [ 'equal("$id", "bucket1")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -128,7 +128,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("fileSecurity", true)'], + 'queries' => [ 'equal("fileSecurity", true)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -138,7 +138,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$response['body']['buckets'][0]['$id'].'")'], + 'queries' => [ 'cursorAfter("' . $response['body']['buckets'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -147,7 +147,6 @@ class StorageCustomServerTest extends Scope $this->assertCount(1, $response['body']['buckets']); $this->assertEquals('bucket1', $response['body']['buckets'][0]['$id']); - return $data; } @@ -162,11 +161,11 @@ class StorageCustomServerTest extends Scope */ $response = $this->client->call( Client::METHOD_GET, - '/storage/buckets/'.$id, + '/storage/buckets/' . $id, array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -179,13 +178,14 @@ class StorageCustomServerTest extends Scope /** * Test for FAILURE */ + $response = $this->client->call( Client::METHOD_GET, '/storage/buckets/empty', array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -197,8 +197,8 @@ class StorageCustomServerTest extends Scope '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -217,7 +217,7 @@ class StorageCustomServerTest extends Scope /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$id, array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -239,7 +239,7 @@ class StorageCustomServerTest extends Scope /** * Test for FAILURE */ - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$id, array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -262,11 +262,11 @@ class StorageCustomServerTest extends Scope */ $response = $this->client->call( Client::METHOD_DELETE, - '/storage/buckets/'.$id, + '/storage/buckets/' . $id, array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) @@ -276,11 +276,11 @@ class StorageCustomServerTest extends Scope $response = $this->client->call( Client::METHOD_GET, - '/storage/buckets/'.$id, + '/storage/buckets/' . $id, array_merge( [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders() ) diff --git a/tests/e2e/Services/Storage/StoragePermissionsScope.php b/tests/e2e/Services/Storage/StoragePermissionsScope.php index e6502cc183..09b35fad36 100644 --- a/tests/e2e/Services/Storage/StoragePermissionsScope.php +++ b/tests/e2e/Services/Storage/StoragePermissionsScope.php @@ -7,7 +7,6 @@ use Tests\E2E\Client; trait StoragePermissionsScope { public array $users = []; - public array $teams = []; public function createUser(string $id, string $email, string $password = 'test123!'): array @@ -19,7 +18,7 @@ trait StoragePermissionsScope ], [ 'userId' => $id, 'email' => $email, - 'password' => $password, + 'password' => $password ]); $this->assertEquals(201, $user['headers']['status-code']); @@ -33,7 +32,8 @@ trait StoragePermissionsScope 'password' => $password, ]); - $session = $this->client->parseCookie((string) $session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $user = [ '$id' => $user['body']['$id'], @@ -54,7 +54,7 @@ trait StoragePermissionsScope { $team = $this->client->call(Client::METHOD_POST, '/teams', $this->getServerHeader(), [ 'teamId' => $id, - 'name' => $name, + 'name' => $name ]); $this->teams[$id] = $team['body']; @@ -63,16 +63,16 @@ trait StoragePermissionsScope public function addToTeam(string $user, string $team, array $roles = []): array { - $membership = $this->client->call(Client::METHOD_POST, '/teams/'.$team.'/memberships', $this->getServerHeader(), [ + $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team . '/memberships', $this->getServerHeader(), [ 'teamId' => $team, 'email' => $this->getCreatedUser($user)['email'], 'roles' => $roles, - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); return [ 'user' => $membership['body']['userId'], - 'membership' => $membership['body']['$id'], + 'membership' => $membership['body']['$id'] ]; } @@ -81,7 +81,7 @@ trait StoragePermissionsScope return [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]; } } diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 7b960b3aa5..83b9042f13 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -3,6 +3,7 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -41,7 +42,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => $teamId, - 'name' => 'Manchester United', + 'name' => 'Manchester United' ]); $this->assertEquals(201, $response2['headers']['status-code']); @@ -58,7 +59,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Newcastle', + 'name' => 'Newcastle' ]); $this->assertEquals(201, $response3['headers']['status-code']); @@ -84,7 +85,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => $teamId, - 'name' => 'John', + 'name' => 'John' ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -103,7 +104,7 @@ trait TeamsBase /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -146,7 +147,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(2)'], + 'queries' => [ 'limit(2)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -156,7 +157,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -166,7 +167,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['greaterThanEqual("total", 0)'], + 'queries' => [ 'greaterThanEqual("total", 0)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -176,7 +177,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("name", ["Arsenal", "Newcastle"])'], + 'queries' => [ 'equal("name", ["Arsenal", "Newcastle"])' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -225,7 +226,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(2)'], + 'queries' => [ 'limit(2)' ], ]); $this->assertEquals(200, $teams['headers']['status-code']); @@ -237,7 +238,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)', 'cursorAfter("'.$teams['body']['teams'][0]['$id'].'")'], + 'queries' => [ 'limit(1)', 'cursorAfter("' . $teams['body']['teams'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -250,7 +251,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)', 'cursorBefore("'.$teams['body']['teams'][1]['$id'].'")'], + 'queries' => [ 'limit(1)', 'cursorBefore("' . $teams['body']['teams'][1]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -266,7 +267,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("unknown")'], + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -284,7 +285,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Demo', + 'name' => 'Demo' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -294,12 +295,12 @@ trait TeamsBase $this->assertIsInt($response['body']['total']); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); - $response = $this->client->call(Client::METHOD_PUT, '/teams/'.$response['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Demo New', + 'name' => 'Demo New' ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -313,7 +314,7 @@ trait TeamsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/teams/'.$response['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -334,7 +335,7 @@ trait TeamsBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Demo', + 'name' => 'Demo' ]); $teamUid = $response['body']['$id']; @@ -348,7 +349,7 @@ trait TeamsBase $dateValidator = new DatetimeValidator(); $this->assertEquals(true, $dateValidator->isValid($response['body']['$createdAt'])); - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -359,7 +360,7 @@ trait TeamsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -379,7 +380,7 @@ trait TeamsBase /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$id.'/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $id . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -393,7 +394,7 @@ trait TeamsBase $this->assertEquals($team['body']['funcKey1'], 'funcValue1'); $this->assertEquals($team['body']['funcKey2'], 'funcValue2'); - $team = $this->client->call(Client::METHOD_GET, '/teams/'.$id.'/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/' . $id . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -404,7 +405,7 @@ trait TeamsBase 'funcKey2' => 'funcValue2', ]); - $team = $this->client->call(Client::METHOD_GET, '/teams/'.$id, array_merge([ + $team = $this->client->call(Client::METHOD_GET, '/teams/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -418,7 +419,7 @@ trait TeamsBase /** * Test for FAILURE */ - $user = $this->client->call(Client::METHOD_PUT, '/teams/'.$id.'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PUT, '/teams/' . $id . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 4a3a2859dd..7b6b439558 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -3,6 +3,7 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -19,7 +20,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -35,51 +36,51 @@ trait TeamsBaseClient $membershipId = $response['body']['memberships'][0]['$id']; - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(1)'], + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(1, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(1)'], + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(0, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("confirm", true)'], + 'queries' => [ 'equal("confirm", true)' ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(1, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("confirm", false)'], + 'queries' => [ 'equal("confirm", false)' ] ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(0, $response['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => $this->getUser()['$id'], + 'search' => $this->getUser()['$id'] ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -91,11 +92,11 @@ trait TeamsBaseClient $this->assertContains('owner', $response['body']['memberships'][0]['roles']); $this->assertContains('player', $response['body']['memberships'][0]['roles']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => $membershipId, + 'search' => $membershipId ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -107,11 +108,11 @@ trait TeamsBaseClient $this->assertContains('owner', $response['body']['memberships'][0]['roles']); $this->assertContains('player', $response['body']['memberships'][0]['roles']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'unknown', + 'search' => 'unknown' ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -137,7 +138,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -156,14 +157,15 @@ trait TeamsBaseClient /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'dasdasd', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid . 'dasdasd', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -178,20 +180,20 @@ trait TeamsBaseClient { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; $name = 'Friend User'; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -209,7 +211,7 @@ trait TeamsBaseClient $this->assertEquals($email, $lastEmail['to'][0]['address']); $this->assertEquals($name, $lastEmail['to'][0]['name']); - $this->assertEquals('Invitation to '.$teamName.' Team at '.$this->getProject()['name'], $lastEmail['subject']); + $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); @@ -219,7 +221,7 @@ trait TeamsBaseClient * Test with UserId * Create user */ - $secondEmail = uniqid().'foe@localhost.test'; + $secondEmail = uniqid() . 'foe@localhost.test'; $secondName = 'Another Foe'; $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'content-type' => 'application/json', @@ -228,7 +230,7 @@ trait TeamsBaseClient 'userId' => 'unique()', 'email' => $secondEmail, 'password' => 'password', - 'name' => $secondName, + 'name' => $secondName ]); $this->assertEquals(201, $response['headers']['status-code']); $userId = $response['body']['$id']; @@ -237,13 +239,13 @@ trait TeamsBaseClient * Test for UserID * Failure */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'userId' => 'abcdefdg', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -252,13 +254,13 @@ trait TeamsBaseClient * Test for UserID * SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'userId' => $userId, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -276,55 +278,56 @@ trait TeamsBaseClient $this->assertEquals($secondEmail, $lastEmail['to'][0]['address']); $this->assertEquals($secondName, $lastEmail['to'][0]['name']); - $this->assertEquals('Invitation to '.$teamName.' Team at '.$this->getProject()['name'], $lastEmail['subject']); + $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(409, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => 'dasdkaskdjaskdjasjkd', 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => 'bad string', - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://example.com/join-us#title', // bad url + 'url' => 'http://example.com/join-us#title' // bad url ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -336,7 +339,7 @@ trait TeamsBaseClient 'membershipUid' => $membershipUid, 'userUid' => $userUid, 'email' => $email, - 'name' => $name, + 'name' => $name ]; } @@ -345,7 +348,7 @@ trait TeamsBaseClient */ public function testListTeamMemberships($data): void { - $memberships = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + $memberships = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -355,11 +358,11 @@ trait TeamsBaseClient $this->assertNotEmpty($memberships['body']['memberships']); $this->assertCount(3, $memberships['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$memberships['body']['memberships'][0]['$id'].'")'], + 'queries' => [ 'cursorAfter("' . $memberships['body']['memberships'][0]['$id'] . '")' ] ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -384,7 +387,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -400,18 +403,19 @@ trait TeamsBaseClient $this->assertCount(2, $response['body']['roles']); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['joined'])); $this->assertEquals(true, $response['body']['confirm']); - $session = $this->client->parseCookie((string) $response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $data['session'] = $session; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals(true, $response['body']['emailVerification']); + /** [START] TESTS TO CHECK PASSWORD UPDATE OF NEW USER CREATED USING TEAM INVITE */ /** * New User tries to update password without old password -> SHOULD PASS @@ -420,9 +424,9 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'password' => 'new-password', + 'password' => 'new-password' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -440,7 +444,7 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', ]); @@ -453,10 +457,10 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'newer-password', - 'oldPassword' => 'new-password', + 'oldPassword' => 'new-password' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -472,7 +476,7 @@ trait TeamsBaseClient /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -483,7 +487,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -494,7 +498,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -505,7 +509,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -516,7 +520,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -527,7 +531,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -554,12 +558,12 @@ trait TeamsBaseClient * Test for SUCCESS */ $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles, + 'roles' => $roles ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -574,12 +578,12 @@ trait TeamsBaseClient /** * Test for unknown team */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.'abc'.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . 'abc' . '/memberships/' . $membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles, + 'roles' => $roles ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -587,26 +591,27 @@ trait TeamsBaseClient /** * Test for unknown membership ID */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.'abc', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . 'abc', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles, + 'roles' => $roles ]); $this->assertEquals(404, $response['headers']['status-code']); + /** * Test for when a user other than the owner tries to update membership */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ], [ - 'roles' => $roles, + 'roles' => $roles ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -615,7 +620,7 @@ trait TeamsBaseClient return $data; } - /** + /** * @depends testUpdateTeamMembershipRoles */ public function testDeleteTeamMembership($data): array @@ -624,7 +629,7 @@ trait TeamsBaseClient $membershipUid = $data['membershipUid'] ?? ''; $session = $data['session'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -641,11 +646,11 @@ trait TeamsBaseClient /** * Test deleting a membership that does not exists */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/dne', [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/dne', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -653,11 +658,11 @@ trait TeamsBaseClient /** * Test deleting another user's membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -669,17 +674,17 @@ trait TeamsBaseClient /** * Test for when a user other than the owner tries to delete their membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -690,7 +695,7 @@ trait TeamsBaseClient /** * Test for when the owner tries to delete their membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -699,7 +704,7 @@ trait TeamsBaseClient $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index 642078d72b..7bb6241c4a 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -17,7 +17,7 @@ trait TeamsBaseServer /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$id.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $id . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -43,7 +43,7 @@ trait TeamsBaseServer /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -62,14 +62,15 @@ trait TeamsBaseServer /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'dasdasd', array_merge([ + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid . 'dasdasd', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(404, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -84,19 +85,19 @@ trait TeamsBaseServer { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -125,50 +126,51 @@ trait TeamsBaseServer /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(409, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => 'dasdkaskdjaskdjasjkd', 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => 'bad string', - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://example.com/join-us#title', // bad url + 'url' => 'http://example.com/join-us#title' // bad url ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -176,7 +178,7 @@ trait TeamsBaseServer return [ 'teamUid' => $teamUid, 'userUid' => $userUid, - 'membershipUid' => $membershipUid, + 'membershipUid' => $membershipUid ]; } @@ -192,12 +194,12 @@ trait TeamsBaseServer * Test for SUCCESS */ $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles, + 'roles' => $roles ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -209,18 +211,19 @@ trait TeamsBaseServer $this->assertEquals($roles[1], $response['body']['roles'][1]); $this->assertEquals($roles[2], $response['body']['roles'][2]); + /** * Test for FAILURE */ $apiKey = $this->getNewKey(['teams.read']); $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $apiKey, + 'x-appwrite-key' => $apiKey ], [ - 'roles' => $roles, + 'roles' => $roles ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -237,7 +240,7 @@ trait TeamsBaseServer $userUid = $data['userUid'] ?? ''; /** Get Team Count */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -250,7 +253,7 @@ trait TeamsBaseServer $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); /** Delete User */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$userUid, array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $userUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -261,11 +264,12 @@ trait TeamsBaseServer sleep(5); /** Get Team Count */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEquals('Arsenal', $response['body']['name']); diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 7c5a667bbc..e86c18a8e2 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; @@ -22,10 +22,10 @@ class TeamsConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_POST, '/teams', \array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => 'console', + 'x-appwrite-project' => 'console' ], $this->getHeaders()), [ 'name' => 'Latest version Team', - 'teamId' => ID::unique(), + 'teamId' => ID::unique() ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -37,9 +37,9 @@ class TeamsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/teams', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', - 'x-appwrite-response-format' => '0.11.0', + 'x-appwrite-response-format' => '0.11.0' ], $this->getHeaders()), [ - 'name' => 'Latest version Team', + 'name' => 'Latest version Team' // Notice "teamId' is not defined ]); @@ -49,14 +49,14 @@ class TeamsConsoleClientTest extends Scope /** * Cleanup, so I don't invalidate some listTeams requests by mistake */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team1Id, \array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team1Id, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team2Id, \array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team2Id, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => 'console', ], $this->getHeaders())); @@ -71,18 +71,18 @@ class TeamsConsoleClientTest extends Scope { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; $name = 'Friend User'; $password = 'password'; // Create a user account before we create a invite so we can check if the user has permissions when it shouldn't $user = $this->client->call(Client::METHOD_POST, '/account', [ 'content-type' => 'application/json', - 'x-appwrite-project' => 'console', ], [ - 'userId' => 'unique()', - 'email' => $email, - 'password' => $password, - 'name' => $name, + 'x-appwrite-project' => 'console'], [ + 'userId' => 'unique()', + 'email' => $email, + 'password' => $password, + 'name' => $name, ], false); $this->assertEquals(201, $user['headers']['status-code']); @@ -90,14 +90,14 @@ class TeamsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => $name, 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -108,7 +108,7 @@ class TeamsConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -117,7 +117,7 @@ class TeamsConsoleClientTest extends Scope $ownerMembershipUid = $response['body']['memberships'][1]['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsCustomClientTest.php b/tests/e2e/Services/Teams/TeamsCustomClientTest.php index 83a8080d1d..3b46cbcb7f 100644 --- a/tests/e2e/Services/Teams/TeamsCustomClientTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomClientTest.php @@ -2,8 +2,8 @@ namespace Tests\E2E\Services\Teams; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; class TeamsCustomClientTest extends Scope diff --git a/tests/e2e/Services/Teams/TeamsCustomServerTest.php b/tests/e2e/Services/Teams/TeamsCustomServerTest.php index 325b5892fc..ccbb598934 100644 --- a/tests/e2e/Services/Teams/TeamsCustomServerTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomServerTest.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Tests\E2E\Client; class TeamsCustomServerTest extends Scope { diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 5842212e07..baf601789a 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -107,7 +107,7 @@ trait UsersBase 'email' => 'sha512@appwrite.io', 'password' => '4243da0a694e8a2f727c8060fe0507c8fa01ca68146c76d2c190805b638c20c6bf6ba04e21f11ae138785d0bff63c416e6f87badbffad37f6dee50094cc38c70', // appwrite (sha512) 'name' => 'SHA512 User', - 'passwordVersion' => 'sha512', + 'passwordVersion' => 'sha512' ]); $this->assertEquals($res['headers']['status-code'], 201); @@ -127,7 +127,7 @@ trait UsersBase 'passwordCpu' => 16384, 'passwordMemory' => 13, 'passwordParallel' => 2, - 'passwordLength' => 64, + 'passwordLength' => 64 ]); $this->assertEquals($res['headers']['status-code'], 201); @@ -191,7 +191,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $userId.'@appwrite.io', + 'email' => $userId . '@appwrite.io', 'password' => 'appwrite', ]); @@ -201,14 +201,14 @@ trait UsersBase foreach ($userIds as $userId) { // Ensure all passwords were re-hashed - $response = $this->client->call(Client::METHOD_GET, '/users/'.$userId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $userId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($userId, $response['body']['$id']); - $this->assertEquals($userId.'@appwrite.io', $response['body']['email']); + $this->assertEquals($userId . '@appwrite.io', $response['body']['email']); $this->assertEquals('argon2', $response['body']['hash']); $this->assertStringStartsWith('$argon2', $response['body']['password']); } @@ -220,7 +220,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $userId.'@appwrite.io', + 'email' => $userId . '@appwrite.io', 'password' => 'appwrite', ]); @@ -349,7 +349,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("name", "'.$user1['name'].'")'], + 'queries' => ['equal("name", "' . $user1['name'] . '")'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -362,7 +362,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("email", "'.$user1['email'].'")'], + 'queries' => ['equal("email", "' . $user1['email'] . '")'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -375,7 +375,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("status", true)'], + 'queries' => ['equal("status", true)'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -391,7 +391,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("status", false)'], + 'queries' => ['equal("status", false)'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -403,7 +403,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("passwordUpdate", "'.$user1['passwordUpdate'].'")'], + 'queries' => ['equal("passwordUpdate", "' . $user1['passwordUpdate'] . '")'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -416,7 +416,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("registration", "'.$user1['registration'].'")'], + 'queries' => ['equal("registration", "' . $user1['registration'] . '")'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -429,7 +429,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("emailVerification", false)'], + 'queries' => ['equal("emailVerification", false)'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -445,7 +445,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("emailVerification", true)'], + 'queries' => ['equal("emailVerification", true)'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -457,7 +457,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("phoneVerification", false)'], + 'queries' => ['equal("phoneVerification", false)'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -469,7 +469,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("phoneVerification", true)'], + 'queries' => ['equal("phoneVerification", true)'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -481,7 +481,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("'.$data['userId'].'")'], + 'queries' => ['cursorAfter("' . $data['userId'] . '")'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -494,7 +494,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorBefore("user1")'], + 'queries' => ['cursorBefore("user1")'] ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -510,7 +510,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'Ronaldo', + 'search' => "Ronaldo", ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -522,7 +522,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'cristiano.ronaldo@manchester-united.co.uk', + 'search' => "cristiano.ronaldo@manchester-united.co.uk", ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -534,7 +534,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'cristiano.ronaldo', + 'search' => "cristiano.ronaldo", ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -546,7 +546,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'manchester', + 'search' => "manchester", ]); $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); @@ -558,7 +558,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'united.co.uk', + 'search' => "united.co.uk", ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -572,7 +572,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'man', + 'search' => "man", ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -602,7 +602,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAfter("unknown")'], + 'queries' => ['cursorAfter("unknown")'] ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -616,7 +616,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -627,7 +627,7 @@ trait UsersBase $this->assertEquals($user['body']['status'], true); $this->assertGreaterThan('2000-01-01 00:00:00', $user['body']['registration']); - $sessions = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/sessions', array_merge([ + $sessions = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/sessions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -670,7 +670,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/name', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/name', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -680,7 +680,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['name'], 'Updated name'); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -737,7 +737,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/email', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -747,7 +747,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['email'], 'users.service@updated.com'); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -804,7 +804,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/password', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/password', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -819,7 +819,7 @@ trait UsersBase 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'email' => 'users.service@updated.com', - 'password' => 'password2', + 'password' => 'password2' ]); $this->assertEquals($session['headers']['status-code'], 201); @@ -836,7 +836,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/status', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/status', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -846,7 +846,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['status'], false); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -865,7 +865,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/verification', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/verification', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -875,7 +875,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['emailVerification'], true); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -895,7 +895,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -909,7 +909,7 @@ trait UsersBase $this->assertEquals($user['body']['funcKey1'], 'funcValue1'); $this->assertEquals($user['body']['funcKey2'], 'funcValue2'); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -923,7 +923,7 @@ trait UsersBase /** * Test for FAILURE */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -932,7 +932,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 400); - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -950,8 +950,8 @@ trait UsersBase /** * Test for SUCCESS */ - $updatedNumber = '+910000000000'; //dummy number - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/phone', array_merge([ + $updatedNumber = "+910000000000"; //dummy number + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/phone', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -961,7 +961,7 @@ trait UsersBase $this->assertEquals($user['headers']['status-code'], 200); $this->assertEquals($user['body']['phone'], $updatedNumber); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -972,12 +972,13 @@ trait UsersBase /** * Test for FAILURE */ - $errorType = 'user_phone_already_exists'; - $user1Id = 'user1'; + + $errorType = "user_phone_already_exists"; + $user1Id = "user1"; $statusCodeForUserPhoneAlredyExists = 409; // adding same number ($updatedNumber) to different user i.e user1 - $response = $this->client->call(Client::METHOD_PATCH, '/users/'.$user1Id.'/phone', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $user1Id . '/phone', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -996,7 +997,7 @@ trait UsersBase public function testUpdateUserNumberSearch($data): void { $id = $data['userId'] ?? ''; - $newNumber = '+910000000000'; //dummy number + $newNumber = "+910000000000"; //dummy number /** * Test for SUCCESS @@ -1066,7 +1067,7 @@ trait UsersBase */ public function testUpdateUserLabels(array $labels, int $expectedStatus, array $expectedLabels, array $data): array { - $user = $this->client->call(Client::METHOD_PUT, '/users/'.$data['userId'].'/labels', array_merge([ + $user = $this->client->call(Client::METHOD_PUT, '/users/' . $data['userId'] . '/labels', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1086,7 +1087,7 @@ trait UsersBase */ public function testUpdateUserLabelsWithoutLabels(array $data): array { - $user = $this->client->call(Client::METHOD_PUT, '/users/'.$data['userId'].'/labels', array_merge([ + $user = $this->client->call(Client::METHOD_PUT, '/users/' . $data['userId'] . '/labels', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -1108,6 +1109,7 @@ trait UsersBase $this->assertEquals(Response::STATUS_CODE_NOT_FOUND, $user['headers']['status-code']); } + /** * @depends testGetUser */ @@ -1116,7 +1118,7 @@ trait UsersBase /** * Test for SUCCESS */ - $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1125,7 +1127,7 @@ trait UsersBase $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1137,7 +1139,7 @@ trait UsersBase $this->assertLessThanOrEqual(1, count($logs['body']['logs'])); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1148,7 +1150,7 @@ trait UsersBase $this->assertIsArray($logs['body']['logs']); $this->assertIsNumeric($logs['body']['total']); - $logs = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1163,47 +1165,47 @@ trait UsersBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['limit(-1)'], + 'queries' => ['limit(-1)'] ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['offset(-1)'], + 'queries' => ['offset(-1)'] ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['equal("$id", "asdf")'], + 'queries' => ['equal("$id", "asdf")'] ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['orderAsc("$id")'], + 'queries' => ['orderAsc("$id")'] ]); $this->assertEquals($response['headers']['status-code'], 400); - $response = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/logs', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => ['cursorAsc("$id")'], + 'queries' => ['cursorAsc("$id")'] ]); $this->assertEquals($response['headers']['status-code'], 400); @@ -1217,7 +1219,7 @@ trait UsersBase /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -1227,7 +1229,7 @@ trait UsersBase /** * Test for FAILURE */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/e2e/Services/Users/UsersConsoleClientTest.php b/tests/e2e/Services/Users/UsersConsoleClientTest.php index cc44520387..8943bfab63 100644 --- a/tests/e2e/Services/Users/UsersConsoleClientTest.php +++ b/tests/e2e/Services/Users/UsersConsoleClientTest.php @@ -2,9 +2,9 @@ namespace Tests\E2E\Services\Users; -use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Client; use Tests\E2E\Scopes\SideConsole; class UsersConsoleClientTest extends Scope @@ -17,9 +17,10 @@ class UsersConsoleClientTest extends Scope /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_GET, '/users/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ 'range' => '32h', ]); @@ -31,7 +32,7 @@ class UsersConsoleClientTest extends Scope */ $response = $this->client->call(Client::METHOD_GET, '/users/usage', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ 'range' => '24h', ]); diff --git a/tests/e2e/Services/Users/UsersCustomServerTest.php b/tests/e2e/Services/Users/UsersCustomServerTest.php index 2442f1bf7d..6b9a990d4c 100644 --- a/tests/e2e/Services/Users/UsersCustomServerTest.php +++ b/tests/e2e/Services/Users/UsersCustomServerTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Users; +use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index 663167e38b..6e30e7abc1 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Webhooks; use Appwrite\Tests\Retry; use CURLFile; use Tests\E2E\Client; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -15,34 +16,34 @@ trait WebhooksBase public static function getWebhookSignature(array $webhook, string $signatureKey): string { $payload = json_encode($webhook['data']); - $url = $webhook['url']; - - return base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + return base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); } + public function testCreateCollection(): array { /** * Create database */ $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'databaseId' => ID::unique(), - 'name' => 'Actors DB', + 'databaseId' => ID::unique(), + 'name' => 'Actors DB', ]); $databaseId = $database['body']['$id']; - /** + /** * Test for SUCCESS */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Actors', @@ -66,8 +67,8 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); @@ -90,30 +91,30 @@ trait WebhooksBase $actorsId = $data['actorsId']; $databaseId = $data['databaseId']; - $firstName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ + $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'firstName', 'size' => 256, 'required' => true, ]); - $lastName = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ + $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'lastName', 'size' => 256, 'required' => true, ]); - $extra = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/attributes/string', array_merge([ + $extra = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'extra', 'size' => 64, @@ -138,9 +139,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -150,10 +151,10 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['key']); $this->assertEquals($webhook['data']['key'], 'extra'); - $removed = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/attributes/'.$extra['body']['key'], array_merge([ + $removed = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/attributes/' . $extra['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals(204, $removed['headers']['status-code']); @@ -164,9 +165,9 @@ trait WebhooksBase // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.attributes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -190,7 +191,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -217,9 +218,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -253,7 +254,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$data['documentId'], array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $data['documentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -279,9 +280,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -314,7 +315,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -336,7 +337,7 @@ trait WebhooksBase $this->assertEquals($document['headers']['status-code'], 201); $this->assertNotEmpty($document['body']['$id']); - $document = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actorsId.'/documents/'.$document['body']['$id'], array_merge([ + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $document['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -349,9 +350,9 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -372,6 +373,7 @@ trait WebhooksBase return $data; } + public function testCreateStorageBucket(): array { /** @@ -380,7 +382,7 @@ trait WebhooksBase $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'bucketId' => ID::unique(), 'name' => 'Test Bucket', @@ -429,10 +431,10 @@ trait WebhooksBase /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'], array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test Bucket Updated', 'fileSecurity' => true, @@ -472,10 +474,10 @@ trait WebhooksBase $bucketId = $data['bucketId']; //enable bucket - $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$data['bucketId'], array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test Bucket Updated', 'fileSecurity' => true, @@ -486,12 +488,12 @@ trait WebhooksBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'.$data['bucketId'].'/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__.'/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -549,7 +551,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/'.$bucketId.'/files/'.$fileId, array_merge([ + $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -605,7 +607,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$data['bucketId'].'/files/'.$data['fileId'], array_merge([ + $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -653,10 +655,10 @@ trait WebhooksBase /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/'.$bucketId, array_merge([ + $bucket = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); $this->assertEquals($bucket['headers']['status-code'], 204); @@ -692,7 +694,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Arsenal', + 'name' => 'Arsenal' ]); $teamId = $team['body']['$id']; @@ -735,11 +737,11 @@ trait WebhooksBase /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$teamId, array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $teamId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'name' => 'Demo New', + 'name' => 'Demo New' ]); $this->assertEquals(200, $team['headers']['status-code']); @@ -778,14 +780,14 @@ trait WebhooksBase { $id = $data['teamId'] ?? ''; - $team = $this->client->call(Client::METHOD_PUT, '/teams/'.$id.'/prefs', array_merge([ + $team = $this->client->call(Client::METHOD_PUT, '/teams/' . $id . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ], + ] ]); $this->assertEquals($team['headers']['status-code'], 200); @@ -794,8 +796,8 @@ trait WebhooksBase $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -828,7 +830,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Chelsea', + 'name' => 'Chelsea' ]); $teamId = $team['body']['$id']; @@ -836,7 +838,7 @@ trait WebhooksBase $this->assertEquals(201, $team['headers']['status-code']); $this->assertNotEmpty($team['body']['$id']); - $team = $this->client->call(Client::METHOD_DELETE, '/teams/'.$team['body']['$id'], array_merge([ + $team = $this->client->call(Client::METHOD_DELETE, '/teams/' . $team['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -873,19 +875,19 @@ trait WebhooksBase public function testCreateTeamMembership($data): array { $teamId = $data['teamId'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_POST, '/teams/'.$teamId.'/memberships', array_merge([ + $team = $this->client->call(Client::METHOD_POST, '/teams/' . $teamId . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $this->assertEquals(201, $team['headers']['status-code']); @@ -940,19 +942,19 @@ trait WebhooksBase public function testDeleteTeamMembership($data): void { $teamId = $data['teamId'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_POST, '/teams/'.$teamId.'/memberships', array_merge([ + $team = $this->client->call(Client::METHOD_POST, '/teams/' . $teamId . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'email' => $email, 'name' => 'Friend User', 'roles' => ['admin', 'editor'], - 'url' => 'http://localhost:5000/join-us#title', + 'url' => 'http://localhost:5000/join-us#title' ]); $membershipId = $team['body']['$id'] ?? ''; @@ -960,7 +962,7 @@ trait WebhooksBase $this->assertEquals(201, $team['headers']['status-code']); $this->assertNotEmpty($team['body']['$id']); - $team = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamId.'/memberships/'.$team['body']['$id'], array_merge([ + $team = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamId . '/memberships/' . $team['body']['$id'], array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php index 48f33a24e5..67c2dec36b 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -4,9 +4,10 @@ namespace Tests\E2E\Services\Webhooks; use Appwrite\Tests\Retry; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -18,7 +19,7 @@ class WebhooksCustomClientTest extends Scope public function testCreateAccount(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -44,8 +45,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -76,7 +77,7 @@ class WebhooksCustomClientTest extends Scope public function testDeleteAccount(): array { - $email = uniqid().'user1@localhost.test'; + $email = uniqid() . 'user1@localhost.test'; $password = 'password'; $name = 'User Name 1'; @@ -106,13 +107,13 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 201); $id = $account['body']['$id']; - $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $account = $this->client->call(Client::METHOD_PATCH, '/account/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($account['headers']['status-code'], 200); @@ -120,8 +121,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -169,13 +170,13 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 201); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -247,15 +248,15 @@ class WebhooksCustomClientTest extends Scope ]); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals($accountSession['headers']['status-code'], 201); - $accountSession = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionId, array_merge([ + $accountSession = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($accountSession['headers']['status-code'], 204); @@ -263,8 +264,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -333,7 +334,7 @@ class WebhooksCustomClientTest extends Scope ]); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals($accountSession['headers']['status-code'], 201); @@ -341,7 +342,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($accountSession['headers']['status-code'], 204); @@ -349,8 +350,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -406,7 +407,7 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 201); $sessionId = $accountSession['body']['$id']; - $session = $this->client->parseCookie((string) $accountSession['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; return array_merge($data, [ 'sessionId' => $sessionId, @@ -429,9 +430,9 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'name' => $newName, + 'name' => $newName ]); $this->assertEquals($account['headers']['status-code'], 200); @@ -440,8 +441,9 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -481,7 +483,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -493,8 +495,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -529,14 +531,14 @@ class WebhooksCustomClientTest extends Scope { $id = $data['id'] ?? ''; $email = $data['email'] ?? ''; - $newEmail = uniqid().'new@localhost.test'; + $newEmail = uniqid() . 'new@localhost.test'; $session = $data['session'] ?? ''; $account = $this->client->call(Client::METHOD_PATCH, '/account/email', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $newEmail, 'password' => 'new-password', @@ -548,8 +550,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -590,12 +592,12 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', 'prefKey2' => 'prefValue2', - ], + ] ]); $this->assertEquals($account['headers']['status-code'], 200); @@ -604,8 +606,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -659,8 +661,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -719,8 +721,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -762,7 +764,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'url' => 'http://localhost/verification', ]); @@ -775,8 +777,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -819,7 +821,7 @@ class WebhooksCustomClientTest extends Scope 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => $secret, @@ -833,8 +835,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -876,7 +878,7 @@ class WebhooksCustomClientTest extends Scope /** * Test for SUCCESS */ - $team = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $team = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -891,8 +893,8 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; - $signatureExpected = base64_encode(hash_hmac('sha1', $url.$payload, $signatureKey, true)); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index 836c81822b..02c3a2dbfd 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\CLI\Console; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -30,10 +31,10 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $actors = $this->client->call(Client::METHOD_PUT, '/databases/'.$databaseId.'/collections/'.$id, array_merge([ + $actors = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Actors1', 'documentSecurity' => true, @@ -48,8 +49,8 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); @@ -72,10 +73,10 @@ class WebhooksCustomServerTest extends Scope $actorsId = $data['actorsId']; $databaseId = $data['databaseId']; - $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/indexes', array_merge([ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'fullname', 'type' => 'key', @@ -96,9 +97,9 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -108,10 +109,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); // Remove index - $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$data['actorsId'].'/indexes/'.$index['body']['key'], array_merge([ + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/indexes/' . $index['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ])); // // wait for database worker to remove index @@ -121,9 +122,9 @@ class WebhooksCustomServerTest extends Scope // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.indexes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -143,7 +144,7 @@ class WebhooksCustomServerTest extends Scope $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders()), [ 'databaseId' => ID::unique(), 'name' => 'Actors DB', @@ -154,10 +155,10 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $actors = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections', array_merge([ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), 'name' => 'Demo', @@ -175,10 +176,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($actors['headers']['status-code'], 201); $this->assertNotEmpty($actors['body']['$id']); - $actors = $this->client->call(Client::METHOD_DELETE, '/databases/'.$databaseId.'/collections/'.$actors['body']['$id'], array_merge([ + $actors = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $this->assertEquals($actors['headers']['status-code'], 204); @@ -189,8 +190,8 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.'.$databaseId.'.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); @@ -207,7 +208,7 @@ class WebhooksCustomServerTest extends Scope public function testCreateUser(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -267,11 +268,11 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$id.'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $id . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'prefs' => ['a' => 'b'], + 'prefs' => ['a' => 'b'] ]); $this->assertEquals($user['headers']['status-code'], 200); @@ -308,7 +309,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/status', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/status', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -355,7 +356,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_DELETE, '/users/'.$data['userId'], array_merge([ + $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -441,7 +442,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_PUT, '/functions/'.$data['functionId'], array_merge([ + $function = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -450,14 +451,14 @@ class WebhooksCustomServerTest extends Scope 'execute' => [Role::any()->toString()], 'vars' => [ 'key1' => 'value1', - ], + ] ]); $this->assertEquals($function['headers']['status-code'], 200); $this->assertEquals($function['body']['$id'], $data['functionId']); // Create variable - $variable = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/variables', array_merge([ + $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -495,16 +496,16 @@ class WebhooksCustomServerTest extends Scope $stderr = ''; $stdout = ''; $folder = 'timeout'; - $code = realpath(__DIR__.'/../../../resources/functions')."/{$folder}/code.tar.gz"; - Console::execute('cd '.realpath(__DIR__.'/../../../resources/functions')."/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); + $code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz"; + Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'entrypoint' => 'index.php', 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), - 'activate' => true, + 'activate' => true ]); $id = $data['functionId'] ?? ''; @@ -545,7 +546,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/functions/'.$id.'/deployments/'.$deploymentId, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $id . '/deployments/' . $deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -593,11 +594,11 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$id.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $id . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'async' => true, + 'async' => true ]); $executionId = $execution['body']['$id'] ?? ''; @@ -664,7 +665,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/'.$id.'/deployments/'.$deploymentId, array_merge([ + $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $id . '/deployments/' . $deploymentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -709,7 +710,7 @@ class WebhooksCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$id, array_merge([ + $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); diff --git a/tests/extensions/Retryable.php b/tests/extensions/Retryable.php index aa85d22eae..61fec0ef12 100644 --- a/tests/extensions/Retryable.php +++ b/tests/extensions/Retryable.php @@ -14,7 +14,6 @@ trait Retryable * accounting for any retries configured by the {@see Retry} annotation. * * @return void - * * @throws \ReflectionException * @throws \Throwable */ @@ -22,15 +21,14 @@ trait Retryable { $retries = $this->getNumberOfRetries(); $ex = null; - for ($i = 0; $i <= $retries; $i++) { + for ($i = 0; $i <= $retries; ++$i) { try { parent::runBare(); - return; - } catch (\Throwable|\Exception $ex) { + } catch (\Throwable | \Exception $ex) { // Swallow the exception until we have exhausted our retries. if ($i !== $retries) { - echo 'Flaky test failed, retrying...'.PHP_EOL; + echo 'Flaky test failed, retrying...' . PHP_EOL; } } } @@ -41,7 +39,6 @@ trait Retryable /** * @return int - * * @throws \ReflectionException */ private function getNumberOfRetries(): int @@ -56,12 +53,11 @@ trait Retryable $attribute = $attributes[0] ?? null; $args = $attribute?->getArguments(); $retries = $args['count'] ?? 0; - return \max(0, $retries); } /** - * @param \ReflectionClass $reflection + * @param \ReflectionClass $reflection * @return \ReflectionClass */ private function getTestCaseRoot(\ReflectionClass $reflection): \ReflectionClass @@ -69,7 +65,6 @@ trait Retryable if ($reflection->getName() === TestCase::class) { return $reflection; } - return $this->getTestCaseRoot($reflection->getParentClass()); } } diff --git a/tests/extensions/TestHook.php b/tests/extensions/TestHook.php index f6db16a227..67c1215c4c 100644 --- a/tests/extensions/TestHook.php +++ b/tests/extensions/TestHook.php @@ -3,11 +3,11 @@ namespace Appwrite\Tests; use PHPUnit\Runner\AfterTestHook; +use Exception; class TestHook implements AfterTestHook { protected const MAX_SECONDS_ALLOWED = 15; - public function executeAfterTest(string $test, float $time): void { printf( diff --git a/tests/resources/functions/php-fn/index.php b/tests/resources/functions/php-fn/index.php index 6da31cd499..7947c4a6a6 100644 --- a/tests/resources/functions/php-fn/index.php +++ b/tests/resources/functions/php-fn/index.php @@ -1,7 +1,7 @@ json([ 'APPWRITE_FUNCTION_ID' => $request['variables']['APPWRITE_FUNCTION_ID'], diff --git a/tests/resources/functions/php-large/index.php b/tests/resources/functions/php-large/index.php index 83140c27ff..84b6a991fe 100644 --- a/tests/resources/functions/php-large/index.php +++ b/tests/resources/functions/php-large/index.php @@ -10,6 +10,6 @@ return function ($request, $response) { 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request['variables']['APPWRITE_FUNCTION_RUNTIME_VERSION'], 'APPWRITE_FUNCTION_EVENT' => $request['variables']['APPWRITE_FUNCTION_EVENT'], 'APPWRITE_FUNCTION_EVENT_DATA' => $request['variables']['APPWRITE_FUNCTION_EVENT_DATA'], - 'UNICODE_TEST' => 'êä', + 'UNICODE_TEST' => "êä" ]); }; diff --git a/tests/resources/functions/php/index.php b/tests/resources/functions/php/index.php index 83140c27ff..84b6a991fe 100644 --- a/tests/resources/functions/php/index.php +++ b/tests/resources/functions/php/index.php @@ -10,6 +10,6 @@ return function ($request, $response) { 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request['variables']['APPWRITE_FUNCTION_RUNTIME_VERSION'], 'APPWRITE_FUNCTION_EVENT' => $request['variables']['APPWRITE_FUNCTION_EVENT'], 'APPWRITE_FUNCTION_EVENT_DATA' => $request['variables']['APPWRITE_FUNCTION_EVENT_DATA'], - 'UNICODE_TEST' => 'êä', + 'UNICODE_TEST' => "êä" ]); }; diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index a3aa78bc6d..3e6a760b25 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -3,12 +3,12 @@ namespace Tests\Unit\Auth; use Appwrite\Auth\Auth; -use PHPUnit\Framework\TestCase; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use PHPUnit\Framework\TestCase; use Utopia\Database\Validator\Roles; class AuthTest extends TestCase @@ -127,13 +127,13 @@ class AuthTest extends TestCase // Scrypt $plain = 'some-scrypt-password'; $hash = 'b448ad7ba88b653b5b56b8053a06806724932d0751988bc9cd0ef7ff059e8ba8a020e1913b7069a650d3f99a1559aba0221f2c277826919513a054e76e339028'; - $generatedHash = Auth::passwordHash($plain, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2]); + $generatedHash = Auth::passwordHash($plain, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2]); - $this->assertEquals(true, Auth::passwordVerify($plain, $generatedHash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); - $this->assertEquals(true, Auth::passwordVerify($plain, $hash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); - $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', ['salt' => 'some-wrong-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); - $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 10, 'costParallel' => 2])); - $this->assertEquals(false, Auth::passwordVerify('wrongPassword', $hash, 'scrypt', ['salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(true, Auth::passwordVerify($plain, $generatedHash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(true, Auth::passwordVerify($plain, $hash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', [ 'salt' => 'some-wrong-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); + $this->assertEquals(false, Auth::passwordVerify($plain, $hash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 10, 'costParallel' => 2])); + $this->assertEquals(false, Auth::passwordVerify('wrongPassword', $hash, 'scrypt', [ 'salt' => 'some-salt', 'length' => 64, 'costCpu' => 16384, 'costMemory' => 12, 'costParallel' => 2])); // ScryptModified tested are in provider-specific tests below @@ -164,7 +164,7 @@ class AuthTest extends TestCase $saltSeparator = 'Bw=='; $signerKey = 'XyEKE9RcTDeLEsL/RjwPDBv/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ=='; - $options = ['salt' => $salt, 'saltSeparator' => $saltSeparator, 'signerKey' => $signerKey]; + $options = [ 'salt' => $salt, 'saltSeparator' => $saltSeparator, 'signerKey' => $signerKey ]; $generatedHash = Auth::passwordHash($plain, 'scryptMod', $options); $this->assertEquals(true, Auth::passwordVerify($plain, $generatedHash, 'scryptMod', $options)); $this->assertEquals(true, Auth::passwordVerify($plain, $hash, 'scryptMod', $options)); @@ -339,7 +339,7 @@ class AuthTest extends TestCase public function testGuestRoles(): void { $user = new Document([ - '$id' => '', + '$id' => '' ]); $roles = Auth::getRoles($user); @@ -349,11 +349,11 @@ class AuthTest extends TestCase public function testUserRoles(): void { - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'labels' => [ 'vip', - 'admin', + 'admin' ], 'emailVerification' => true, 'phoneVerification' => true, @@ -364,18 +364,18 @@ class AuthTest extends TestCase 'confirm' => true, 'roles' => [ 'administrator', - 'moderator', - ], + 'moderator' + ] ], [ '$id' => ID::custom('abc'), 'teamId' => ID::custom('def'), 'confirm' => true, 'roles' => [ - 'guest', - ], - ], - ], + 'guest' + ] + ] + ] ]); $roles = Auth::getRoles($user); @@ -414,7 +414,7 @@ class AuthTest extends TestCase public function testPrivilegedUserRoles(): void { Authorization::setRole(Auth::USER_ROLE_OWNER); - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'emailVerification' => true, 'phoneVerification' => true, @@ -425,18 +425,18 @@ class AuthTest extends TestCase 'confirm' => true, 'roles' => [ 'administrator', - 'moderator', - ], + 'moderator' + ] ], [ '$id' => ID::custom('abc'), 'teamId' => ID::custom('def'), 'confirm' => true, 'roles' => [ - 'guest', - ], - ], - ], + 'guest' + ] + ] + ] ]); $roles = Auth::getRoles($user); @@ -458,7 +458,7 @@ class AuthTest extends TestCase public function testAppUserRoles(): void { Authorization::setRole(Auth::USER_ROLE_APPS); - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'memberships' => [ [ @@ -467,18 +467,18 @@ class AuthTest extends TestCase 'confirm' => true, 'roles' => [ 'administrator', - 'moderator', - ], + 'moderator' + ] ], [ '$id' => ID::custom('abc'), 'teamId' => ID::custom('def'), 'confirm' => true, 'roles' => [ - 'guest', - ], - ], - ], + 'guest' + ] + ] + ] ]); $roles = Auth::getRoles($user); diff --git a/tests/unit/Auth/Validator/PasswordDictionaryTest.php b/tests/unit/Auth/Validator/PasswordDictionaryTest.php index 283d5c79fa..fd7f51ff16 100644 --- a/tests/unit/Auth/Validator/PasswordDictionaryTest.php +++ b/tests/unit/Auth/Validator/PasswordDictionaryTest.php @@ -4,6 +4,7 @@ namespace Tests\Unit\Auth\Validator; use Appwrite\Auth\Validator\PasswordDictionary; use PHPUnit\Framework\TestCase; +use Utopia\Database\Document; class PasswordDictionaryTest extends TestCase { diff --git a/tests/unit/Docker/ComposeTest.php b/tests/unit/Docker/ComposeTest.php index 350b41a820..56448ffd01 100644 --- a/tests/unit/Docker/ComposeTest.php +++ b/tests/unit/Docker/ComposeTest.php @@ -12,7 +12,7 @@ class ComposeTest extends TestCase public function setUp(): void { - $data = @file_get_contents(__DIR__.'/../../resources/docker/docker-compose.yml'); + $data = @file_get_contents(__DIR__ . '/../../resources/docker/docker-compose.yml'); if ($data === false) { throw new Exception('Failed to read compose file'); diff --git a/tests/unit/Docker/EnvTest.php b/tests/unit/Docker/EnvTest.php index b271bde504..e6c9b8cadf 100644 --- a/tests/unit/Docker/EnvTest.php +++ b/tests/unit/Docker/EnvTest.php @@ -12,7 +12,7 @@ class EnvTest extends TestCase public function setUp(): void { - $data = @file_get_contents(__DIR__.'/../../resources/docker/.env'); + $data = @file_get_contents(__DIR__ . '/../../resources/docker/.env'); if ($data === false) { throw new Exception('Failed to read compose file'); @@ -34,10 +34,10 @@ class EnvTest extends TestCase public function testExport(): void { - $this->assertEquals('_APP_X=value1 + $this->assertEquals("_APP_X=value1 _APP_Y=value2 _APP_Z=value3 _APP_W=value5= -', $this->object->export()); +", $this->object->export()); } } diff --git a/tests/unit/Event/EventTest.php b/tests/unit/Event/EventTest.php index 13f2bb4fd2..a328c8d599 100644 --- a/tests/unit/Event/EventTest.php +++ b/tests/unit/Event/EventTest.php @@ -10,16 +10,15 @@ use Utopia\App; class EventTest extends TestCase { protected ?Event $object = null; - protected string $queue = ''; public function setUp(): void { $redisHost = App::getEnv('_APP_REDIS_HOST', ''); $redisPort = App::getEnv('_APP_REDIS_PORT', ''); - \Resque::setBackend($redisHost.':'.$redisPort); + \Resque::setBackend($redisHost . ':' . $redisPort); - $this->queue = 'v1-tests'.uniqid(); + $this->queue = 'v1-tests' . uniqid(); $this->object = new Event($this->queue, 'TestsV1'); } @@ -86,7 +85,7 @@ class EventTest extends TestCase public function testGenerateEvents(): void { $event = Event::generateEvents('users.[userId].create', [ - 'userId' => 'torsten', + 'userId' => 'torsten' ]); $this->assertCount(4, $event); $this->assertContains('users.torsten.create', $event); @@ -95,7 +94,7 @@ class EventTest extends TestCase $this->assertContains('users.*', $event); $event = Event::generateEvents('users.[userId].update.email', [ - 'userId' => 'torsten', + 'userId' => 'torsten' ]); $this->assertCount(6, $event); $this->assertContains('users.torsten.update.email', $event); @@ -152,9 +151,10 @@ class EventTest extends TestCase $this->assertContains('databases.chaptersDB.collections.*.documents.*', $event); $this->assertContains('databases.chaptersDB.collections.*.documents.*.create', $event); + try { $event = Event::generateEvents('collections.[collectionId].documents.[documentId].create', [ - 'collectionId' => 'chapters', + 'collectionId' => 'chapters' ]); $this->fail(); } catch (\Throwable $th) { diff --git a/tests/unit/General/CollectionsTest.php b/tests/unit/General/CollectionsTest.php index 8596b857a8..73a9ccd0c2 100644 --- a/tests/unit/General/CollectionsTest.php +++ b/tests/unit/General/CollectionsTest.php @@ -10,7 +10,7 @@ class CollectionsTest extends TestCase public function setUp(): void { - $this->collections = require 'app/config/collections.php'; + $this->collections = require('app/config/collections.php'); } public function testDuplicateRules(): void diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 14ec84a8e6..6fe7dda71f 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -3,9 +3,9 @@ namespace Tests\Unit\Messaging; use Appwrite\Auth\Auth; +use Utopia\Database\Document; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; -use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -17,15 +17,10 @@ class MessagingChannelsTest extends TestCase public $connectionsPerChannel = 10; public Realtime $realtime; - public $connectionsCount = 0; - public $connectionsAuthenticated = 0; - public $connectionsGuest = 0; - public $connectionsTotal = 0; - public $allChannels = [ 'files', 'files.1', @@ -56,19 +51,19 @@ class MessagingChannelsTest extends TestCase for ($i = 0; $i < $this->connectionsPerChannel; $i++) { foreach ($this->allChannels as $index => $channel) { $user = new Document([ - '$id' => ID::custom('user'.$this->connectionsCount), + '$id' => ID::custom('user' . $this->connectionsCount), 'memberships' => [ [ - '$id' => ID::custom('member'.$i), - 'teamId' => ID::custom('team'.$i), + '$id' => ID::custom('member' . $i), + 'teamId' => ID::custom('team' . $i), 'confirm' => true, 'roles' => [ empty($index % 2) ? Auth::USER_ROLE_ADMIN : 'member', - ], - ], - ], + ] + ] + ] ]); $roles = Auth::getRoles($user); @@ -92,7 +87,7 @@ class MessagingChannelsTest extends TestCase for ($i = 0; $i < $this->connectionsPerChannel; $i++) { foreach ($this->allChannels as $index => $channel) { $user = new Document([ - '$id' => '', + '$id' => '' ]); $roles = Auth::getRoles($user); @@ -175,8 +170,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ], - ], + ] + ] ]; $receivers = $this->realtime->getSubscribers($event); @@ -199,7 +194,7 @@ class MessagingChannelsTest extends TestCase { $roles = [ Role::guests()->toString(), - Role::users()->toString(), + Role::users()->toString() ]; foreach ($this->allChannels as $index => $channel) { foreach ($roles as $role) { @@ -211,8 +206,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ], - ], + ] + ] ]; $receivers = $this->realtime->getSubscribers($event); @@ -237,7 +232,7 @@ class MessagingChannelsTest extends TestCase foreach ($this->allChannels as $index => $channel) { $permissions = []; for ($i = 0; $i < $this->connectionsPerChannel; $i++) { - $permissions[] = Role::user(ID::custom('user'.(! empty($i) ? $i : '').$index))->toString(); + $permissions[] = Role::user(ID::custom('user' . (!empty($i) ? $i : '') . $index))->toString(); } $event = [ 'project' => '1', @@ -245,8 +240,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ], - ], + ] + ] ]; $receivers = $this->realtime->getSubscribers($event); @@ -271,8 +266,8 @@ class MessagingChannelsTest extends TestCase $permissions = []; for ($i = 0; $i < $this->connectionsPerChannel; $i++) { - $permissions[] = Role::team(ID::custom('team'.$i))->toString(); - $permissions[] = Role::member(ID::custom('member'.$i))->toString(); + $permissions[] = Role::team(ID::custom('team' . $i))->toString(); + $permissions[] = Role::member(ID::custom('member' . $i))->toString(); } $event = [ 'project' => '1', @@ -280,8 +275,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ], - ], + ] + ] ]; $receivers = $this->realtime->getSubscribers($event); @@ -303,8 +298,8 @@ class MessagingChannelsTest extends TestCase : 'member'; $permissions = [ - Role::team(ID::custom('team'.$index), $role)->toString(), - Role::member(ID::custom('member'.$index))->toString(), + Role::team(ID::custom('team' . $index), $role)->toString(), + Role::member(ID::custom('member' . $index))->toString() ]; $event = [ @@ -313,8 +308,8 @@ class MessagingChannelsTest extends TestCase 'data' => [ 'channels' => [ 0 => $channel, - ], - ], + ] + ] ]; $receivers = $this->realtime->getSubscribers($event); diff --git a/tests/unit/Messaging/MessagingGuestTest.php b/tests/unit/Messaging/MessagingGuestTest.php index 660e9519e3..1aaa1febca 100644 --- a/tests/unit/Messaging/MessagingGuestTest.php +++ b/tests/unit/Messaging/MessagingGuestTest.php @@ -27,8 +27,8 @@ class MessagingGuestTest extends TestCase 'channels' => [ 0 => 'documents', 1 => 'documents', - ], - ], + ] + ] ]; $receivers = $realtime->getSubscribers($event); diff --git a/tests/unit/Messaging/MessagingTest.php b/tests/unit/Messaging/MessagingTest.php index d6ae6b095b..c2e3971945 100644 --- a/tests/unit/Messaging/MessagingTest.php +++ b/tests/unit/Messaging/MessagingTest.php @@ -2,9 +2,9 @@ namespace Tests\Unit\Messaging; +use Utopia\Database\Document; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; -use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -44,8 +44,8 @@ class MessagingTest extends TestCase 'data' => [ 'channels' => [ 0 => 'account.123', - ], - ], + ] + ] ]; $receivers = $realtime->getSubscribers($event); @@ -148,7 +148,7 @@ class MessagingTest extends TestCase public function testConvertChannelsGuest(): void { $user = new Document([ - '$id' => '', + '$id' => '' ]); $channels = [ @@ -156,7 +156,7 @@ class MessagingTest extends TestCase 1 => 'documents', 2 => 'documents.789', 3 => 'account', - 4 => 'account.456', + 4 => 'account.456' ]; $channels = Realtime::convertChannels($channels, $user->getId()); @@ -170,30 +170,30 @@ class MessagingTest extends TestCase public function testConvertChannelsUser(): void { - $user = new Document([ + $user = new Document([ '$id' => ID::custom('123'), 'memberships' => [ [ 'teamId' => ID::custom('abc'), 'roles' => [ 'administrator', - 'moderator', - ], + 'moderator' + ] ], [ 'teamId' => ID::custom('def'), 'roles' => [ - 'guest', - ], - ], - ], + 'guest' + ] + ] + ] ]); $channels = [ 0 => 'files', 1 => 'documents', 2 => 'documents.789', 3 => 'account', - 4 => 'account.456', + 4 => 'account.456' ]; $channels = Realtime::convertChannels($channels, $user->getId()); @@ -321,7 +321,7 @@ class MessagingTest extends TestCase Permission::update(Role::team('123abc')), Permission::delete(Role::team('123abc')), ], - 'fileSecurity' => true, + 'fileSecurity' => true ]) ); diff --git a/tests/unit/Migration/MigrationTest.php b/tests/unit/Migration/MigrationTest.php index c322cc9635..13f9b9a3f5 100644 --- a/tests/unit/Migration/MigrationTest.php +++ b/tests/unit/Migration/MigrationTest.php @@ -22,12 +22,12 @@ abstract class MigrationTest extends TestCase /** * Runs every document fix twice, to prevent corrupted data on multiple migrations. * - * @param Document $document + * @param Document $document */ protected function fixDocument(Document $document) { return $this->method->invokeArgs($this->migration, [ - $this->method->invokeArgs($this->migration, [$document]), + $this->method->invokeArgs($this->migration, [$document]) ]); } @@ -36,14 +36,14 @@ abstract class MigrationTest extends TestCase */ public function testMigrationVersions(): void { - require_once __DIR__.'/../../../app/init.php'; + require_once __DIR__ . '/../../../app/init.php'; foreach (Migration::$versions as $class) { - $this->assertTrue(class_exists('Appwrite\\Migration\\Version\\'.$class)); + $this->assertTrue(class_exists('Appwrite\\Migration\\Version\\' . $class)); } // Test if current version exists // Only test official releases - skip if latest is release candidate - if (! (\str_contains(APP_VERSION_STABLE, 'RC'))) { + if (!(\str_contains(APP_VERSION_STABLE, 'RC'))) { $this->assertArrayHasKey(APP_VERSION_STABLE, Migration::$versions); } } @@ -60,8 +60,8 @@ abstract class MigrationTest extends TestCase 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'], - ], + 'd' => ['a', 'b', 'c'] + ] ], [ 'bool' => true, 'string' => 'abc', @@ -71,8 +71,8 @@ abstract class MigrationTest extends TestCase 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'], - ], + 'd' => ['a', 'b', 'c'] + ] ])); $this->assertFalse(Migration::hasDifference([ 'bool' => true, @@ -83,15 +83,15 @@ abstract class MigrationTest extends TestCase 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'], - ], + 'd' => ['a', 'b', 'c'] + ] ], [ 'string' => 'abc', 'assoc' => [ 'a' => true, 'b' => 'abc', 'c' => 123, - 'd' => ['a', 'b', 'c'], + 'd' => ['a', 'b', 'c'] ], 'int' => 123, 'array' => ['a', 'b', 'c'], @@ -99,40 +99,40 @@ abstract class MigrationTest extends TestCase ])); $this->assertTrue(Migration::hasDifference([ - 'a' => true, + 'a' => true ], [ - 'b' => true, + 'b' => true ])); $this->assertTrue(Migration::hasDifference([ - 'a' => 'true', + 'a' => 'true' ], [ - 'a' => true, + 'a' => true ])); $this->assertTrue(Migration::hasDifference([ - 'a' => true, + 'a' => true ], [ - 'a' => false, + 'a' => false ])); $this->assertTrue(Migration::hasDifference([ 'nested' => [ - 'a' => true, - ], + 'a' => true + ] ], [ - 'nested' => [], + 'nested' => [] ])); $this->assertTrue(Migration::hasDifference([ 'assoc' => [ 'bool' => true, 'string' => 'abc', 'int' => 123, - 'array' => ['a', 'b', 'c'], - ], + 'array' => ['a', 'b', 'c'] + ] ], [ 'nested' => [ 'a' => true, 'int' => '123', - 'array' => ['a', 'b', 'c'], - ], + 'array' => ['a', 'b', 'c'] + ] ])); } } diff --git a/tests/unit/Network/Validators/EmailTest.php b/tests/unit/Network/Validators/EmailTest.php index d74f2c30fc..f629ed6ddc 100755 --- a/tests/unit/Network/Validators/EmailTest.php +++ b/tests/unit/Network/Validators/EmailTest.php @@ -3,13 +3,12 @@ /** * Utopia PHP Framework * + * @package Framework + * @subpackage Tests * * @link https://github.com/utopia-php/framework - * * @author Appwrite Team - * * @version 1.0 RC4 - * * @license The MIT License (MIT) */ diff --git a/tests/unit/Template/TemplateTest.php b/tests/unit/Template/TemplateTest.php index ab4cb49742..1ca1595ca3 100644 --- a/tests/unit/Template/TemplateTest.php +++ b/tests/unit/Template/TemplateTest.php @@ -14,9 +14,10 @@ class TemplateTest extends TestCase public function setUp(): void { - $this->object = new Template(__DIR__.'/../../resources/template.tpl'); + $this->object = new Template(__DIR__ . '/../../resources/template.tpl'); $this->object - ->setParam('{{world}}', 'WORLD'); + ->setParam('{{world}}', 'WORLD') + ; } public function tearDown(): void diff --git a/tests/unit/Usage/StatsTest.php b/tests/unit/Usage/StatsTest.php index 72fadab70e..0c9914f4bd 100644 --- a/tests/unit/Usage/StatsTest.php +++ b/tests/unit/Usage/StatsTest.php @@ -13,26 +13,25 @@ use Utopia\Queue\Connection; class StatsTest extends TestCase { protected ?Connection $connection = null; - protected ?Client $client = null; protected const QUEUE_NAME = 'usage-test-q'; public function setUp(): void { - $env = App::getEnv('_APP_CONNECTIONS_QUEUE', AppwriteURL::unparse([ - 'scheme' => 'redis', - 'host' => App::getEnv('_APP_REDIS_HOST', 'redis'), - 'port' => App::getEnv('_APP_REDIS_PORT', '6379'), - 'user' => App::getEnv('_APP_REDIS_USER', ''), - 'pass' => App::getEnv('_APP_REDIS_PASS', ''), - ])); + $env = App::getEnv('_APP_CONNECTIONS_QUEUE', AppwriteURL::unparse([ + 'scheme' => 'redis', + 'host' => App::getEnv('_APP_REDIS_HOST', 'redis'), + 'port' => App::getEnv('_APP_REDIS_PORT', '6379'), + 'user' => App::getEnv('_APP_REDIS_USER', ''), + 'pass' => App::getEnv('_APP_REDIS_PASS', ''), + ])); $dsn = explode('=', $env); $dsn = $dsn[1] ?? ''; $dsn = new DSN($dsn); $this->connection = new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort()); - $this->client = new Client(self::QUEUE_NAME, $this->connection); + $this->client = new Client(self::QUEUE_NAME, $this->connection); } public function tearDown(): void @@ -42,13 +41,13 @@ class StatsTest extends TestCase public function testSamePayload(): void { $inToQueue = [ - 'key_1' => 'value_1', - 'key_2' => 'value_2', + 'key_1' => 'value_1', + 'key_2' => 'value_2', ]; $result = $this->client->enqueue($inToQueue); $this->assertTrue($result); - $outFromQueue = $this->connection->leftPopArray('utopia-queue.queue.'.self::QUEUE_NAME, 0)['payload']; + $outFromQueue = $this->connection->leftPopArray('utopia-queue.queue.' . self::QUEUE_NAME, 0)['payload']; $this->assertNotEmpty($outFromQueue); $this->assertSame($inToQueue, $outFromQueue); } diff --git a/tests/unit/Utopia/Lists.php b/tests/unit/Utopia/Lists.php index ac54a293a5..8f003cc2ae 100644 --- a/tests/unit/Utopia/Lists.php +++ b/tests/unit/Utopia/Lists.php @@ -12,7 +12,7 @@ class Lists extends Model ->addRule('singles', [ 'type' => 'single', 'default' => '', - 'array' => true, + 'array' => true ]); } diff --git a/tests/unit/Utopia/Nested.php b/tests/unit/Utopia/Nested.php index b18f73977e..2be0e85762 100644 --- a/tests/unit/Utopia/Nested.php +++ b/tests/unit/Utopia/Nested.php @@ -15,7 +15,7 @@ class Nested extends Model ]) ->addRule('single', [ 'type' => 'single', - 'default' => '', + 'default' => '' ]); } diff --git a/tests/unit/Utopia/Request/Filters/V15Test.php b/tests/unit/Utopia/Request/Filters/V15Test.php index 7a37213d44..70bf71d4cb 100644 --- a/tests/unit/Utopia/Request/Filters/V15Test.php +++ b/tests/unit/Utopia/Request/Filters/V15Test.php @@ -28,7 +28,7 @@ class V15Test extends TestCase return [ 'basic test' => [ ['limit' => '12', 'offset' => '0'], - ['queries' => ['limit(12)', 'offset(0)']], + ['queries' => ['limit(12)', 'offset(0)']] ], ]; } @@ -72,8 +72,8 @@ class V15Test extends TestCase 'limit(12)', 'offset(0)', 'cursorBefore("abcd")', - 'orderAsc("")', - ], + 'orderAsc("")' + ] ], ], ]; @@ -90,7 +90,7 @@ class V15Test extends TestCase [ 'queries' => [ 'cursorAfter("abcd")', - ], + ] ], ], 'cursorDirection invalid' => [ @@ -101,7 +101,7 @@ class V15Test extends TestCase [ 'queries' => [ 'cursorAfter("abcd")', - ], + ] ], ], ]; @@ -117,7 +117,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderDesc("")', - ], + ] ], ], 'orderType invalid' => [ @@ -127,7 +127,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderAsc("")', - ], + ] ], ], ]; @@ -239,7 +239,7 @@ class V15Test extends TestCase 'write invalid' => [ ['write' => ['invalid', 'invalid:a']], ['permissions' => ['write("invalid:a")']], - ], + ] ]; } @@ -320,7 +320,7 @@ class V15Test extends TestCase 'queries' => [ 'orderDesc("lastName")', 'orderAsc("firstName")', - ], + ] ], ], 'orderType only' => [ @@ -330,7 +330,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderDesc("")', - ], + ] ], ], 'orderType invalid' => [ @@ -341,7 +341,7 @@ class V15Test extends TestCase [ 'queries' => [ 'orderAsc("lastName")', - ], + ] ], ], ]; @@ -371,7 +371,7 @@ class V15Test extends TestCase 'greaterThan("age", [20])', 'greaterThanEqual("age", [21])', 'search("address", ["pla"])', - ], + ] ], ], ]; @@ -439,7 +439,7 @@ class V15Test extends TestCase 'team:b', 'team:c/member', 'member:z', - ], + ] ], ], ]; diff --git a/tests/unit/Utopia/Response/Filters/V15Test.php b/tests/unit/Utopia/Response/Filters/V15Test.php index cf08d9bb70..fc38e5320b 100644 --- a/tests/unit/Utopia/Response/Filters/V15Test.php +++ b/tests/unit/Utopia/Response/Filters/V15Test.php @@ -2,11 +2,11 @@ namespace Tests\Unit\Utopia\Response\Filters; -use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filters\V15; -use PHPUnit\Framework\TestCase; +use Appwrite\Utopia\Response; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use PHPUnit\Framework\TestCase; class V15Test extends TestCase { @@ -196,7 +196,7 @@ class V15Test extends TestCase 'maximumFileSize' => 100, 'allowedFileExtensions' => [ 'jpg', - 'png', + 'png' ], 'encryption' => false, 'antivirus' => false, @@ -213,7 +213,7 @@ class V15Test extends TestCase 'maximumFileSize' => 100, 'allowedFileExtensions' => [ 'jpg', - 'png', + 'png' ], 'encryption' => false, 'antivirus' => false, @@ -275,8 +275,8 @@ class V15Test extends TestCase [ 'startTime' => 1592981250, 'endTime' => 1592981250, - ], - ], + ] + ] ]; } @@ -346,14 +346,14 @@ class V15Test extends TestCase 'status' => 'available', 'required' => true, 'array' => false, - 'default' => false, + 'default' => false ], 'indexes' => [ 'key' => 'index1', 'type' => 'primary', 'status' => 'available', 'attributes' => [], - 'orders' => [], + 'orders' => [] ], ], [ @@ -361,10 +361,10 @@ class V15Test extends TestCase '$createdAt' => 1592981250, '$updatedAt' => 1592981250, '$read' => [ - 'role:all', + 'role:all' ], '$write' => [ - 'user:608f9da25e7e1', + 'user:608f9da25e7e1' ], 'databaseId' => '5e5ea5c16897e', 'name' => 'My Collection', @@ -376,14 +376,14 @@ class V15Test extends TestCase 'status' => 'available', 'required' => true, 'array' => false, - 'default' => false, + 'default' => false ], 'indexes' => [ 'key' => 'index1', 'type' => 'primary', 'status' => 'available', 'attributes' => [], - 'orders' => [], + 'orders' => [] ], ], ], @@ -511,7 +511,7 @@ class V15Test extends TestCase '$databaseId' => '5e5ea5c15117e', '$createdAt' => '2020-06-24T06:47:30.000Z', '$updatedAt' => '2020-06-24T06:47:30.000Z', - '$permissions' => [Permission::read(Role::any())], + '$permissions' => [Permission::read(Role::any())] ], [ '$id' => '5e5ea5c16897e', @@ -605,7 +605,7 @@ class V15Test extends TestCase '$createdAt' => '2020-06-24T06:47:30.000Z', '$updatedAt' => '2020-06-24T06:47:30.000Z', '$permissions' => [ - 'any', + "any" ], 'functionId' => '5e5ea6g16897e', 'trigger' => 'http', @@ -614,14 +614,14 @@ class V15Test extends TestCase 'response' => '', 'stdout' => '', 'stderr' => '', - 'duration' => 0.4, + 'duration' => 0.4 ], [ '$id' => '5e5ea5c16897e', '$createdAt' => 1592981250, '$updatedAt' => 1592981250, '$read' => [ - 'role:all', + "role:all" ], 'functionId' => '5e5ea6g16897e', 'trigger' => 'http', @@ -629,7 +629,7 @@ class V15Test extends TestCase 'statusCode' => 0, 'response' => '', 'stderr' => '', - 'time' => 0.4, + 'time' => 0.4 ], ], ]; @@ -730,37 +730,37 @@ class V15Test extends TestCase 'key' => 'key', 'value' => 'value', 'functionId' => '5e5ea5c16897e', - ], + ] ], 'events' => [ - 'account.create', + 'account.create' ], 'schedule' => '5 4 * * *', 'scheduleNext' => '2020-06-24T06:48:12.000Z', 'schedulePrevious' => '2020-06-24T06:47:17.000Z', - 'timeout' => 1592981237, + 'timeout' => 1592981237 ], [ '$id' => '5e5ea5c16897e', '$createdAt' => 1592981250, '$updatedAt' => 1592981250, 'execute' => [ - 'role:member', + 'role:member' ], 'name' => 'My Function', 'status' => 'enabled', 'runtime' => 'python-3.8', 'deployment' => '5e5ea5c16897e', 'vars' => [ - 'key' => 'value', + 'key' => 'value' ], 'events' => [ - 'account.create', + 'account.create' ], 'schedule' => '5 4 * * *', 'scheduleNext' => 1592981292, 'schedulePrevious' => 1592981237, - 'timeout' => 1592981237, + 'timeout' => 1592981237 ], ], 'enabled false' => [ @@ -877,7 +877,7 @@ class V15Test extends TestCase 'deviceBrand' => 'Google', 'deviceModel' => 'Nexus 5', 'countryCode' => 'US', - 'countryName' => 'United States', + 'countryName' => 'United States' ], [ 'event' => 'account.sessions.create', @@ -900,8 +900,8 @@ class V15Test extends TestCase 'deviceBrand' => 'Google', 'deviceModel' => 'Nexus 5', 'countryCode' => 'US', - 'countryName' => 'United States', - ], + 'countryName' => 'United States' + ] ], ]; } diff --git a/tests/unit/Utopia/ResponseTest.php b/tests/unit/Utopia/ResponseTest.php index f7be5a03a4..e4389b3953 100644 --- a/tests/unit/Utopia/ResponseTest.php +++ b/tests/unit/Utopia/ResponseTest.php @@ -2,9 +2,9 @@ namespace Tests\Unit\Utopia; +use Exception; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filters\V11; -use Exception; use PHPUnit\Framework\TestCase; use Swoole\Http\Response as SwooleResponse; use Utopia\Database\Document; @@ -80,8 +80,8 @@ class ResponseTest extends TestCase 'string' => 'lorem ipsum', 'integer' => 123, 'boolean' => true, - 'hidden' => 'secret', - ]), + 'hidden' => 'secret' + ]) ], 'hidden' => 'secret', ]), 'lists'); @@ -107,8 +107,8 @@ class ResponseTest extends TestCase 'string' => 'lorem ipsum', 'integer' => 123, 'boolean' => true, - 'hidden' => 'secret', - ]), + 'hidden' => 'secret' + ]) ], 'hidden' => 'secret', ]), @@ -116,7 +116,7 @@ class ResponseTest extends TestCase 'string' => 'lorem ipsum', 'integer' => 123, 'boolean' => true, - 'hidden' => 'secret', + 'hidden' => 'secret' ]), 'hidden' => 'secret', ]), 'nested'); @@ -126,6 +126,7 @@ class ResponseTest extends TestCase $this->assertArrayNotHasKey('hidden', $output); $this->assertCount(1, $output['lists']['singles']); + $single = $output['single']; $this->assertArrayHasKey('string', $single); $this->assertArrayHasKey('integer', $single); diff --git a/tests/unit/Utopia/Single.php b/tests/unit/Utopia/Single.php index 6e9fd3c9ec..3bd09ef6da 100644 --- a/tests/unit/Utopia/Single.php +++ b/tests/unit/Utopia/Single.php @@ -12,7 +12,7 @@ class Single extends Model ->addRule('string', [ 'type' => self::TYPE_STRING, 'example' => '5e5ea5c16897e', - 'required' => true, + 'required' => true ]) ->addRule('integer', [ 'type' => self::TYPE_INTEGER, @@ -27,7 +27,7 @@ class Single extends Model ->addRule('required', [ 'type' => self::TYPE_STRING, 'default' => 'default', - 'required' => true, + 'required' => true ]); } From ec540002636c9802d2bd54366f6e3e87340244a9 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 01:54:25 +0530 Subject: [PATCH 20/72] adds test for target controllers --- app/config/errors.php | 2 +- app/controllers/api/account.php | 90 +++++++------- app/controllers/api/users.php | 44 ++++--- tests/e2e/Scopes/ProjectCustom.php | 2 + tests/e2e/Services/Account/AccountBase.php | 2 +- .../Account/AccountCustomClientTest.php | 112 ++++++++++++++++++ tests/e2e/Services/Users/UsersBase.php | 94 +++++++++++++++ 7 files changed, 278 insertions(+), 68 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index 5942c6027c..add3562cda 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -243,7 +243,7 @@ return [ Exception::USER_TARGET_ALREADY_EXISTS => [ 'name' => Exception::USER_TARGET_ALREADY_EXISTS, 'description' => 'A target with the same ID already exists.', - 'code' => 404, + 'code' => 409, ], /** Teams */ diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 46acd2efdb..046297f5ef 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1834,9 +1834,9 @@ App::get('/v1/account/targets') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TARGET_LIST) - ->inject('response') ->inject('user') - ->action(function (Response $response, Document $user) { + ->inject('response') + ->action(function (Document $user, Response $response) { $targets = $user->getAttribute('targets', []); @@ -1900,13 +1900,13 @@ App::get('/v1/account/targets/:targetId') ->label('sdk.description', '/docs/references/account/get-Target.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk.response.model', Response::MODEL_TARGET) ->label('sdk.offline.model', '/account/targets') ->label('sdk.offline.key', '{targetId}') ->param('targetId', '', new UID(), 'Target ID.') - ->inject('response') ->inject('user') - ->action(function (string $targetId, Response $response, Document $user) { + ->inject('response') + ->action(function (string $targetId, Document $user, Response $response) { $target = $user->find('$id', $targetId, 'targets'); @@ -2999,9 +2999,12 @@ App::put('/v1/account/verification/phone') }); App::post('/v1/account/targets') - ->desc('Create User Target') + ->desc('Create Account\'s Target') ->groups(['api', 'account']) ->label('event', 'users.[userId].targets.[targetId].create') + ->label('audits.event', 'target.create') + ->label('audits.resource', 'user/{response.userId}') + ->label('audits.userId', '{response.userId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'account') @@ -3010,26 +3013,20 @@ App::post('/v1/account/targets') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('userId', '', new UID(), 'ID of the user.', false) - ->param('targetId', '', new UID(), 'Target ID.', false) - ->param('providerId', '', new UID(), 'ID of the provider.', false) - ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', false) + ->param('targetId', '', new UID(), 'Target ID.') + ->param('providerId', '', new UID(), 'Provider ID.') + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') + ->inject('user') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, string $providerId, string $identifier, Response $response, Database $dbForProject, Event $events) { - $provider = $dbForProject->getDocument('providers', $providerId); + ->action(function (string $targetId, string $providerId, string $identifier, Document $user, Response $response, Database $dbForProject, Event $events) { + $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); } - $user = $dbForProject->getDocument('users', $userId); - - if ($user->isEmpty()) { - throw new Exception(Exception::USER_NOT_FOUND); - } - $target = $dbForProject->getDocument('targets', $targetId); if (!$target->isEmpty()) { @@ -3038,29 +3035,34 @@ App::post('/v1/account/targets') $target = $dbForProject->createDocument('targets', new Document([ '$id' => $targetId, - // TO DO: what permissions should be given when created a target. '$permissions' => [ - Permission::read(Role::any()) + Permission::read(Role::user($user->getId())), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), 'providerType' => null, - 'userId' => $userId, + 'userId' => $user->getId(), 'userInternalId' => $user->getInternalId(), 'identifier' => $identifier, ])); $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId); + ->setParam('userId', $user->getId()) + ->setParam('targetId', $targetId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); }); App::patch('/v1/account/targets/:targetId/identifier') - ->desc('Update user target\'s identifier') + ->desc('Update account\'s target identifier') ->groups(['api', 'account']) ->label('event', 'users.[userId].targets.[targetId].update') + ->label('audits.event', 'target.update') + ->label('audits.resource', 'user/{response.userId}') + ->label('audits.userId', '{response.userId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'account') @@ -3069,19 +3071,13 @@ App::patch('/v1/account/targets/:targetId/identifier') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('userId', '', new UID(), 'ID of the user.', false) - ->param('targetId', '', new UID(), 'Target ID.', false) - ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true) + ->param('targetId', '', new UID(), 'Target ID.') + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') + ->inject('user') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { - - $user = $dbForProject->getDocument('users', $userId); - - if ($user->isEmpty()) { - throw new Exception(Exception::USER_NOT_FOUND); - } + ->action(function (string $targetId, string $identifier, Document $user, Response $response, Database $dbForProject, Event $events) { $target = $dbForProject->getDocument('targets', $targetId); @@ -3096,37 +3092,34 @@ App::patch('/v1/account/targets/:targetId/identifier') $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId); + ->setParam('userId', $user->getId()) + ->setParam('targetId', $targetId); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); }); App::delete('/v1/account/targets/:targetId') - ->desc('Delete user target') + ->desc('Delete account\'s target') ->groups(['api', 'account']) ->label('event', 'users.[userId].targets.[targetId].delete') + ->label('audits.event', 'target.delete') + ->label('audits.resource', 'user/{response.userId}') + ->label('audits.userId', '{response.userId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'account') ->label('sdk.method', 'deleteTarget') ->label('sdk.description', '/docs/references/account/delete-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) - ->param('userId', '', new UID(), 'ID of the user.', false) - ->param('targetId', '', new UID(), 'Target ID.', false) + ->param('targetId', '', new UID(), 'Target ID.') + ->inject('user') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { - - $user = $dbForProject->getDocument('users', $userId); - - if ($user->isEmpty()) { - throw new Exception(Exception::USER_NOT_FOUND); - } + ->action(function (string $targetId, Document $user, Response $response, Database $dbForProject, Event $events) { $target = $dbForProject->getDocument('targets', $targetId); @@ -3136,13 +3129,14 @@ App::delete('/v1/account/targets/:targetId') $target = $dbForProject->deleteDocument('targets', $target->getId()); $dbForProject->deleteCachedDocument('users', $user->getId()); - $user = $dbForProject->getDocument('users', $userId); + $user = $dbForProject->getDocument('users', $user->getId()); // clone user object to send to workers $clone = clone $user; $events - ->setParam('userId', $userId) + ->setParam('userId', $user->getId()) + ->setParam('targetId', $targetId) ->setPayload($response->output($clone, Response::MODEL_USER)); $response->noContent(); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index cf94135351..e5599c762d 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -376,6 +376,8 @@ App::post('/v1/users/:userId/targets') ->desc('Create User Target') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].create') + ->label('audits.event', 'target.create') + ->label('audits.resource', 'user/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -384,14 +386,14 @@ App::post('/v1/users/:userId/targets') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('userId', '', new UID(), 'ID of the user.', false) - ->param('targetId', '', new UID(), 'Target ID.', false) - ->param('providerId', '', new UID(), 'ID of the provider.', false) - ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', false) + ->param('userId', '', new UID(), 'User ID.') + ->param('targetId', '', new UID(), 'Target ID.') + ->param('providerId', '', new UID(), 'Provider ID.') + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, string $providerId, string $identifier, Response $response, Database $dbForProject, Event $events) { + ->action(function (string $userId, string $targetId, string $providerId, string $identifier, Response $response, Database $dbForProject, Event $events) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -425,7 +427,8 @@ App::post('/v1/users/:userId/targets') ])); $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId); + ->setParam('userId', $userId) + ->setParam('targetId', $targetId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); @@ -532,7 +535,7 @@ App::get('/v1/users/:userId/prefs') App::get('/v1/users/:userId/targets/:targetId') ->desc('Get User Target') ->groups(['api', 'users']) - ->label('scope', 'users.read') + ->label('scope', 'targets.read') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'getTarget') @@ -725,7 +728,7 @@ App::get('/v1/users/:userId/logs') App::get('/v1/users/:userId/targets') ->desc('List User Targets') ->groups(['api', 'users']) - ->label('scope', 'users.read') + ->label('scope', 'targets.read') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'listTargets') @@ -1215,6 +1218,8 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->desc('Update user target\'s identifier') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].update') + ->label('audits.event', 'target.update') + ->label('audits.resource', 'user/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -1223,13 +1228,13 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('userId', '', new UID(), 'ID of the user.', false) - ->param('targetId', '', new UID(), 'Target ID.', false) - ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true) + ->param('userId', '', new UID(), 'User ID.') + ->param('targetId', '', new UID(), 'Target ID.') + ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, string $identifier, Response $response, Database $dbForProject, Event $events) { + ->action(function (string $userId, string $targetId, string $identifier, Response $response, Database $dbForProject, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -1250,10 +1255,10 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') $dbForProject->deleteCachedDocument('users', $user->getId()); $events - ->setParam('userId', $userId); + ->setParam('userId', $userId) + ->setParam ('targetId', $targetId); $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); }); @@ -1388,20 +1393,22 @@ App::delete('/v1/users/:userId/targets/:targetId') ->desc('Delete user target') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].delete') + ->label('audits.event', 'target.delete') + ->label('audits.resource', 'user/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'deleteTarget') ->label('sdk.description', '/docs/references/users/delete-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) - ->param('userId', '', new UID(), 'ID of the user.', false) - ->param('targetId', '', new UID(), 'Target ID.', false) + ->param('userId', '', new UID(), 'User ID.') + ->param('targetId', '', new UID(), 'Target ID.') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function (string $targetId, string $userId, Response $response, Database $dbForProject, Event $events) { + ->action(function (string $userId, string $targetId, Response $response, Database $dbForProject, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -1424,6 +1431,7 @@ App::delete('/v1/users/:userId/targets/:targetId') $events ->setParam('userId', $userId) + ->setParam('targetId', $targetId) ->setPayload($response->output($clone, Response::MODEL_USER)); $response->noContent(); diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index ee41129fde..2a1b0a8039 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -81,6 +81,8 @@ trait ProjectCustom 'locale.read', 'avatars.read', 'health.read', + 'targets.read', + 'targets.write', 'providers.read', 'providers.write', 'messages.read', diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 291d55b221..c611b6e920 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -363,7 +363,7 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 200); $this->assertIsArray($response['body']['logs']); $this->assertNotEmpty($response['body']['logs']); - $this->assertCount(3, $response['body']['logs']); + $this->assertCount(5, $response['body']['logs']); $this->assertIsNumeric($response['body']['total']); $this->assertContains($response['body']['logs'][1]['event'], ["session.create"]); $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index d225496a65..d429854ec8 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -116,6 +116,118 @@ class AccountCustomClientTest extends Scope return []; } + /** + * @depends testCreateAccountSession + */ + public function testCreateAccountTarget(array $data): array + { + $session = $data['session'] ?? ''; + $apiKey = $this->getProject()['apiKey']; + + $provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $apiKey, + ], [ + 'name' => 'Sengrid1', + 'apiKey' => 'my-apikey' + ]); + $this->assertEquals(201, $provider['headers']['status-code']); + $response = $this->client->call(Client::METHOD_POST, '/account/targets', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]), [ + 'targetId' => ID::unique(), + 'providerId' => $provider['body']['$id'], + 'identifier' => 'my-token', + ]); + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals($provider['body']['$id'], $response['body']['providerId']); + $this->assertEquals('my-token', $response['body']['identifier']); + return ['target' => $response['body'], 'session' => $session]; + } + + /** + * @depends testCreateAccountTarget + */ + public function testUpdateAccountTarget(array $data): array + { + $session = $data['session'] ?? ''; + $target = $data['target']; + $response = $this->client->call(Client::METHOD_PATCH, '/account/targets/' . $target['$id'] .'/identifier', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]), [ + 'identifier' => 'my-updated-token', + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('my-updated-token', $response['body']['identifier']); + return $data; + } + + /** + * @depends testCreateAccountSession + */ + public function testListAccountTarget(array $data) + { + $session = $data['session'] ?? ''; + $response = $this->client->call(Client::METHOD_GET, '/account/targets', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ])); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['total']); + } + + /** + * @depends testCreateAccountTarget + */ + public function testGetAccountTarget(array $data) + { + $session = $data['session'] ?? ''; + $target = $data['target']; + + $response = $this->client->call(Client::METHOD_GET, '/account/targets/' .$target['$id'], array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ])); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($data['target']['$id'], $response['body']['$id']); + } + + /** + * @depends testUpdateAccountTarget + */ + public function testDeleteAccountTarget(array $data) + { + $session = $data['session'] ?? ''; + $target = $data['target']; + + $response = $this->client->call(Client::METHOD_DELETE, '/account/targets/' .$target['$id'], array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ])); + $this->assertEquals(204, $response['headers']['status-code']); + $response = $this->client->call(Client::METHOD_GET, '/account/targets', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ])); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(0, $response['body']['total']); + } + public function testBlockedAccount(): array { $email = uniqid() . 'user@localhost.test'; diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index baf601789a..1d859a626d 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -1211,6 +1211,100 @@ trait UsersBase $this->assertEquals($response['headers']['status-code'], 400); } + /** + * @depends testGetUser + */ + public function testCreateUserTarget(array $data): array + { + $provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'name' => 'Sengrid1', + 'apiKey' => 'my-apikey' + ]); + $this->assertEquals(201, $provider['headers']['status-code']); + $response = $this->client->call(Client::METHOD_POST, '/users/' . $data['userId'] . '/targets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'targetId' => ID::unique(), + 'providerId' => $provider['body']['$id'], + 'identifier' => 'my-token', + ]); + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals($provider['body']['$id'], $response['body']['providerId']); + $this->assertEquals('my-token', $response['body']['identifier']); + return $response['body']; + } + + /** + * @depends testCreateUserTarget + */ + public function testUpdateUserTarget(array $data): array + { + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/targets/' . $data['$id'] .'/identifier', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'identifier' => 'my-updated-token', + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('my-updated-token', $response['body']['identifier']); + return $response['body']; + } + + /** + * @depends testGetUser + */ + public function testListUserTarget(array $data) + { + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['total']); + } + + /** + * @depends testUpdateUserTarget + */ + public function testGetUserTarget(array $data) + { + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets/' .$data['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($data['$id'], $response['body']['$id']); + } + + /** + * @depends testUpdateUserTarget + */ + public function testDeleteUserTarget(array $data) + { + $response = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'] . '/targets/' .$data['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals(204, $response['headers']['status-code']); + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(0, $response['body']['total']); + } + /** * @depends testGetUser */ From a95c29d546a5988e0bfc6077820efd14cd22e55c Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 01:55:08 +0530 Subject: [PATCH 21/72] lint fix --- app/controllers/api/account.php | 2 +- app/controllers/api/users.php | 2 +- .../e2e/Services/Account/AccountCustomClientTest.php | 8 ++++---- tests/e2e/Services/Messaging/MessagingServerTest.php | 1 - tests/e2e/Services/Users/UsersBase.php | 12 ++++++------ 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 046297f5ef..332103cf80 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1906,7 +1906,7 @@ App::get('/v1/account/targets/:targetId') ->param('targetId', '', new UID(), 'Target ID.') ->inject('user') ->inject('response') - ->action(function (string $targetId, Document $user, Response $response) { + ->action(function (string $targetId, Document $user, Response $response) { $target = $user->find('$id', $targetId, 'targets'); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index e5599c762d..7984fb24d9 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1256,7 +1256,7 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') $events ->setParam('userId', $userId) - ->setParam ('targetId', $targetId); + ->setParam('targetId', $targetId); $response ->dynamic($target, Response::MODEL_TARGET); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index d429854ec8..39fa8d0fa5 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -119,7 +119,7 @@ class AccountCustomClientTest extends Scope /** * @depends testCreateAccountSession */ - public function testCreateAccountTarget(array $data): array + public function testCreateAccountTarget(array $data): array { $session = $data['session'] ?? ''; $apiKey = $this->getProject()['apiKey']; @@ -156,7 +156,7 @@ class AccountCustomClientTest extends Scope { $session = $data['session'] ?? ''; $target = $data['target']; - $response = $this->client->call(Client::METHOD_PATCH, '/account/targets/' . $target['$id'] .'/identifier', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/account/targets/' . $target['$id'] . '/identifier', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -193,7 +193,7 @@ class AccountCustomClientTest extends Scope $session = $data['session'] ?? ''; $target = $data['target']; - $response = $this->client->call(Client::METHOD_GET, '/account/targets/' .$target['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/account/targets/' . $target['$id'], array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -211,7 +211,7 @@ class AccountCustomClientTest extends Scope $session = $data['session'] ?? ''; $target = $data['target']; - $response = $this->client->call(Client::METHOD_DELETE, '/account/targets/' .$target['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/account/targets/' . $target['$id'], array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 9bc9f93caf..7b93ab29ac 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -187,5 +187,4 @@ class MessagingServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } } - } diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 1d859a626d..947a3a5cd9 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -1214,7 +1214,7 @@ trait UsersBase /** * @depends testGetUser */ - public function testCreateUserTarget(array $data): array + public function testCreateUserTarget(array $data): array { $provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', [ 'content-type' => 'application/json', @@ -1239,13 +1239,13 @@ trait UsersBase $this->assertEquals('my-token', $response['body']['identifier']); return $response['body']; } - + /** * @depends testCreateUserTarget */ public function testUpdateUserTarget(array $data): array { - $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/targets/' . $data['$id'] .'/identifier', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/targets/' . $data['$id'] . '/identifier', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1256,7 +1256,7 @@ trait UsersBase $this->assertEquals('my-updated-token', $response['body']['identifier']); return $response['body']; } - + /** * @depends testGetUser */ @@ -1276,7 +1276,7 @@ trait UsersBase */ public function testGetUserTarget(array $data) { - $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets/' .$data['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets/' . $data['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -1290,7 +1290,7 @@ trait UsersBase */ public function testDeleteUserTarget(array $data) { - $response = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'] . '/targets/' .$data['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'] . '/targets/' . $data['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], From 82d220e15846d74693a9272fe57f99c629e5aa3e Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 13:43:30 +0530 Subject: [PATCH 22/72] fixes audit events --- app/controllers/api/account.php | 6 ++--- app/controllers/api/messaging.php | 38 +++++++++++++++---------------- app/controllers/api/users.php | 6 ++--- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 332103cf80..4f64965a0b 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3002,7 +3002,7 @@ App::post('/v1/account/targets') ->desc('Create Account\'s Target') ->groups(['api', 'account']) ->label('event', 'users.[userId].targets.[targetId].create') - ->label('audits.event', 'target.create') + ->label('audits.event', 'targets.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') ->label('scope', 'targets.write') @@ -3060,7 +3060,7 @@ App::patch('/v1/account/targets/:targetId/identifier') ->desc('Update account\'s target identifier') ->groups(['api', 'account']) ->label('event', 'users.[userId].targets.[targetId].update') - ->label('audits.event', 'target.update') + ->label('audits.event', 'targets.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') ->label('scope', 'targets.write') @@ -3103,7 +3103,7 @@ App::delete('/v1/account/targets/:targetId') ->desc('Delete account\'s target') ->groups(['api', 'account']) ->label('event', 'users.[userId].targets.[targetId].delete') - ->label('audits.event', 'target.delete') + ->label('audits.event', 'targets.delete') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') ->label('scope', 'targets.write') diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1ff95fbeea..4d97323f3b 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -86,7 +86,7 @@ App::get('/v1/messaging/providers/:id') App::post('/v1/messaging/providers/mailgun') ->desc('Create Mailgun Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -118,7 +118,7 @@ App::post('/v1/messaging/providers/mailgun') App::patch('/v1/messaging/providers/:id/mailgun') ->desc('Update Mailgun Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -172,7 +172,7 @@ App::patch('/v1/messaging/providers/:id/mailgun') App::post('/v1/messaging/providers/sendgrid') ->desc('Create Sendgrid Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -202,7 +202,7 @@ App::post('/v1/messaging/providers/sendgrid') App::patch('/v1/messaging/providers/:id/sendgrid') ->desc('Update Sendgrid Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -251,7 +251,7 @@ App::patch('/v1/messaging/providers/:id/sendgrid') App::post('/v1/messaging/providers/msg91') ->desc('Create Msg91 Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -283,7 +283,7 @@ App::post('/v1/messaging/providers/msg91') App::patch('/v1/messaging/providers/:id/msg91') ->desc('Update Msg91 Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -337,7 +337,7 @@ App::patch('/v1/messaging/providers/:id/msg91') App::post('/v1/messaging/providers/telesign') ->desc('Create Telesign Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -369,7 +369,7 @@ App::post('/v1/messaging/providers/telesign') App::patch('/v1/messaging/providers/:id/telesign') ->desc('Update Telesign Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -423,7 +423,7 @@ App::patch('/v1/messaging/providers/:id/telesign') App::post('/v1/messaging/providers/textmagic') ->desc('Create Textmagic Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -455,7 +455,7 @@ App::post('/v1/messaging/providers/textmagic') App::patch('/v1/messaging/providers/:id/textmagic') ->desc('Update Textmagic Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -509,7 +509,7 @@ App::patch('/v1/messaging/providers/:id/textmagic') App::post('/v1/messaging/providers/twilio') ->desc('Create Twilio Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -541,7 +541,7 @@ App::post('/v1/messaging/providers/twilio') App::patch('/v1/messaging/providers/:id/twilio') ->desc('Update Twilio Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -595,7 +595,7 @@ App::patch('/v1/messaging/providers/:id/twilio') App::post('/v1/messaging/providers/vonage') ->desc('Create Vonage Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -627,7 +627,7 @@ App::post('/v1/messaging/providers/vonage') App::patch('/v1/messaging/providers/:id/vonage') ->desc('Update Vonage Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -684,7 +684,7 @@ App::patch('/v1/messaging/providers/:id/vonage') App::post('/v1/messaging/providers/fcm') ->desc('Create FCM Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -714,7 +714,7 @@ App::post('/v1/messaging/providers/fcm') App::patch('/v1/messaging/providers/:id/fcm') ->desc('Update FCM Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -758,7 +758,7 @@ App::patch('/v1/messaging/providers/:id/fcm') App::post('/v1/messaging/providers/apns') ->desc('Create APNS Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.create') + ->label('audits.event', 'providers.create') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -796,7 +796,7 @@ App::post('/v1/messaging/providers/apns') App::patch('/v1/messaging/providers/:id/apns') ->desc('Update APNS Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.update') + ->label('audits.event', 'providers.update') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -856,7 +856,7 @@ App::patch('/v1/messaging/providers/:id/apns') App::delete('/v1/messaging/providers/:id') ->desc('Delete Provider') ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.providers.delete') + ->label('audits.event', 'providers.delete') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 7984fb24d9..d27d487ebb 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -376,7 +376,7 @@ App::post('/v1/users/:userId/targets') ->desc('Create User Target') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].create') - ->label('audits.event', 'target.create') + ->label('audits.event', 'targets.create') ->label('audits.resource', 'user/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) @@ -1218,7 +1218,7 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->desc('Update user target\'s identifier') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].update') - ->label('audits.event', 'target.update') + ->label('audits.event', 'targets.update') ->label('audits.resource', 'user/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) @@ -1393,7 +1393,7 @@ App::delete('/v1/users/:userId/targets/:targetId') ->desc('Delete user target') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].delete') - ->label('audits.event', 'target.delete') + ->label('audits.event', 'targets.delete') ->label('audits.resource', 'user/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) From e8cc60b0c2c972815c55a89cd044f5346bdea7da Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 14:05:51 +0530 Subject: [PATCH 23/72] adds audit resource in messaging controllers --- app/controllers/api/messaging.php | 20 ++++++++++++++++++++ app/controllers/api/users.php | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 4d97323f3b..a44ef63fb0 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -87,6 +87,7 @@ App::post('/v1/messaging/providers/mailgun') ->desc('Create Mailgun Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -119,6 +120,7 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->desc('Update Mailgun Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -173,6 +175,7 @@ App::post('/v1/messaging/providers/sendgrid') ->desc('Create Sendgrid Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -203,6 +206,7 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->desc('Update Sendgrid Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -252,6 +256,7 @@ App::post('/v1/messaging/providers/msg91') ->desc('Create Msg91 Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -284,6 +289,7 @@ App::patch('/v1/messaging/providers/:id/msg91') ->desc('Update Msg91 Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -338,6 +344,7 @@ App::post('/v1/messaging/providers/telesign') ->desc('Create Telesign Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -370,6 +377,7 @@ App::patch('/v1/messaging/providers/:id/telesign') ->desc('Update Telesign Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -424,6 +432,7 @@ App::post('/v1/messaging/providers/textmagic') ->desc('Create Textmagic Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -456,6 +465,7 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->desc('Update Textmagic Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -510,6 +520,7 @@ App::post('/v1/messaging/providers/twilio') ->desc('Create Twilio Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -542,6 +553,7 @@ App::patch('/v1/messaging/providers/:id/twilio') ->desc('Update Twilio Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -596,6 +608,7 @@ App::post('/v1/messaging/providers/vonage') ->desc('Create Vonage Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -628,6 +641,7 @@ App::patch('/v1/messaging/providers/:id/vonage') ->desc('Update Vonage Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -685,6 +699,7 @@ App::post('/v1/messaging/providers/fcm') ->desc('Create FCM Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -715,6 +730,7 @@ App::patch('/v1/messaging/providers/:id/fcm') ->desc('Update FCM Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -759,6 +775,7 @@ App::post('/v1/messaging/providers/apns') ->desc('Create APNS Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -797,6 +814,7 @@ App::patch('/v1/messaging/providers/:id/apns') ->desc('Update APNS Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -857,6 +875,7 @@ App::delete('/v1/messaging/providers/:id') ->desc('Delete Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.delete') + ->label('audits.resource', 'providers/{request.id}') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'messaging') @@ -885,6 +904,7 @@ App::post('/v1/messaging/messages/email') ->desc('Send an email.') ->groups(['api', 'messaging']) ->label('audits.event', 'messages.create') + ->label('audits.resource', 'messages/{response.$id}') ->label('scope', 'messages.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d27d487ebb..df5ea7925d 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -377,7 +377,7 @@ App::post('/v1/users/:userId/targets') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].create') ->label('audits.event', 'targets.create') - ->label('audits.resource', 'user/{response.$id}') + ->label('audits.resource', 'user/{response.userId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -1219,7 +1219,7 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].update') ->label('audits.event', 'targets.update') - ->label('audits.resource', 'user/{response.$id}') + ->label('audits.resource', 'user/{response.userId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -1394,7 +1394,7 @@ App::delete('/v1/users/:userId/targets/:targetId') ->groups(['api', 'users']) ->label('event', 'users.[userId].targets.[targetId].delete') ->label('audits.event', 'targets.delete') - ->label('audits.resource', 'user/{response.$id}') + ->label('audits.resource', 'user/{response.userId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') From eafea1c41d811ac71cbb313bf8f13072282d2013 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 14:31:22 +0530 Subject: [PATCH 24/72] formats messaging controller --- app/controllers/api/messaging.php | 1662 ++++++++++++++--------------- 1 file changed, 831 insertions(+), 831 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index a44ef63fb0..753abc8432 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -15,939 +15,939 @@ use Utopia\Validator\ArrayList; use Utopia\Validator\Text; App::get('/v1/messaging/providers') - ->desc('List Providers') - ->groups(['api', 'messaging']) - ->label('scope', 'providers.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listProviders') - ->label('sdk.description', '/docs/references/messaging/list-providers.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) - ->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) - ->inject('dbForProject') - ->inject('response') - ->action(function (array $queries, Database $dbForProject, Response $response) { - $queries = Query::parseQueries($queries); + ->desc('List Providers') + ->groups(['api', 'messaging']) + ->label('scope', 'providers.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'listProviders') + ->label('sdk.description', '/docs/references/messaging/list-providers.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) + ->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) + ->inject('dbForProject') + ->inject('response') + ->action(function (array $queries, Database $dbForProject, Response $response) { + $queries = Query::parseQueries($queries); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); - $cursor = reset($cursor); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); - if ($cursor) { - $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ - Query::equal('$id', [$providerId]), - Query::limit(1), - ])); + if ($cursor) { + $providerId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ + Query::equal('$id', [$providerId]), + Query::limit(1), + ])); - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument[0]); } - $cursor->setValue($cursorDocument[0]); - } - - $filterQueries = Query::groupByType($queries)['filters']; - $response->dynamic(new Document([ - 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), - 'indexes' => $dbForProject->find('providers', $queries), - ]), Response::MODEL_PROVIDER_LIST); - }); + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), + 'indexes' => $dbForProject->find('providers', $queries), + ]), Response::MODEL_PROVIDER_LIST); + }); App::get('/v1/messaging/providers/:id') - ->desc('Get Provider') - ->groups(['api', 'messaging']) - ->label('scope', 'providers.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getProvider') - ->label('sdk.description', '/docs/references/messaging/get-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', null, new UID(), 'Provider ID.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Get Provider') + ->groups(['api', 'messaging']) + ->label('scope', 'providers.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'getProvider') + ->label('sdk.description', '/docs/references/messaging/get-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', null, new UID(), 'Provider ID.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $response->dynamic($provider, Response::MODEL_PROVIDER); - }); + $response->dynamic($provider, Response::MODEL_PROVIDER); + }); /** * Email Providers */ App::post('/v1/messaging/providers/mailgun') - ->desc('Create Mailgun Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderMailgun') - ->label('sdk.description', '/docs/references/messaging/create-provider-mailgun.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('apiKey', '', new Text(0), 'Mailgun API Key.') - ->param('domain', '', new Text(0), 'Mailgun Domain.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'mailgun', - 'type' => 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - 'domain' => $domain, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Mailgun Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderMailgun') + ->label('sdk.description', '/docs/references/messaging/create-provider-mailgun.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('apiKey', '', new Text(0), 'Mailgun API Key.') + ->param('domain', '', new Text(0), 'Mailgun Domain.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'mailgun', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + 'domain' => $domain, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/mailgun') - ->desc('Update Mailgun Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderMailgun') - ->label('sdk.description', '/docs/references/messaging/update-provider-mailgun.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) - ->param('domain', '', new Text(0), 'Mailgun Domain.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Mailgun Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderMailgun') + ->label('sdk.description', '/docs/references/messaging/update-provider-mailgun.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) + ->param('domain', '', new Text(0), 'Mailgun Domain.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'mailgun') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($apiKey || $domain) { - // Check if all five variables are present - if ($apiKey && $domain) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'domain' => $domain - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'mailgun') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($apiKey || $domain) { + // Check if all five variables are present + if ($apiKey && $domain) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'domain' => $domain, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::post('/v1/messaging/providers/sendgrid') - ->desc('Create Sendgrid Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderSendgrid') - ->label('sdk.description', '/docs/references/messaging/create-provider-sendgrid.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('apiKey', '', new Text(0), 'Sendgrid API key.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'sendgrid', - 'type' => 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Sendgrid Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderSendgrid') + ->label('sdk.description', '/docs/references/messaging/create-provider-sendgrid.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('apiKey', '', new Text(0), 'Sendgrid API key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'sendgrid', + 'type' => 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/sendgrid') - ->desc('Update Sendgrid Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderSendgrid') - ->label('sdk.description', '/docs/references/messaging/update-provider-sendgrid.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Sendgrid Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderSendgrid') + ->label('sdk.description', '/docs/references/messaging/update-provider-sendgrid.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'sendgrid') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'sendgrid') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($apiKey) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey - ]); - } + if ($apiKey) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + ]); + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); /** * SMS Providers */ App::post('/v1/messaging/providers/msg91') - ->desc('Create Msg91 Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderMsg91') - ->label('sdk.description', '/docs/references/messaging/create-provider-msg91.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') - ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'msg91', - 'type' => 'sms', - 'credentials' => [ - 'senderId' => $senderId, - 'authKey' => $authKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Msg91 Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderMsg91') + ->label('sdk.description', '/docs/references/messaging/create-provider-msg91.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') + ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'msg91', + 'type' => 'sms', + 'credentials' => [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/msg91') - ->desc('Update Msg91 Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderMsg91') - ->label('sdk.description', '/docs/references/messaging/update-provider-msg91.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) - ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Msg91 Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderMsg91') + ->label('sdk.description', '/docs/references/messaging/update-provider-msg91.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) + ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'msg91') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($senderId || $authKey) { - // Check if all five variables are present - if ($senderId && $authKey) { - $provider->setAttribute('credentials', [ - 'senderId' => $senderId, - 'authKey' => $authKey - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'msg91') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($senderId || $authKey) { + // Check if all five variables are present + if ($senderId && $authKey) { + $provider->setAttribute('credentials', [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::post('/v1/messaging/providers/telesign') - ->desc('Create Telesign Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderTelesign') - ->label('sdk.description', '/docs/references/messaging/create-provider-telesign.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('username', '', new Text(0), 'Telesign username.') - ->param('password', '', new Text(0), 'Telesign password.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'telesign', - 'type' => 'sms', - 'credentials' => [ - 'username' => $username, - 'password' => $password, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Telesign Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderTelesign') + ->label('sdk.description', '/docs/references/messaging/create-provider-telesign.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('username', '', new Text(0), 'Telesign username.') + ->param('password', '', new Text(0), 'Telesign password.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $username, string $password, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'telesign', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'password' => $password, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/telesign') - ->desc('Update Telesign Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderTelesign') - ->label('sdk.description', '/docs/references/messaging/update-provider-telesign.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('username', '', new Text(0), 'Telesign username.', true) - ->param('password', '', new Text(0), 'Telesign password.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Telesign Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderTelesign') + ->label('sdk.description', '/docs/references/messaging/update-provider-telesign.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('username', '', new Text(0), 'Telesign username.', true) + ->param('password', '', new Text(0), 'Telesign password.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'telesign') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($username || $password) { - // Check if all five variables are present - if ($username && $password) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'password' => $password - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'telesign') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($username || $password) { + // Check if all five variables are present + if ($username && $password) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'password' => $password, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::post('/v1/messaging/providers/textmagic') - ->desc('Create Textmagic Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderTextmagic') - ->label('sdk.description', '/docs/references/messaging/create-provider-textmagic.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('username', '', new Text(0), 'Textmagic username.') - ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'text-magic', - 'type' => 'sms', - 'credentials' => [ - 'username' => $username, - 'apiKey' => $apiKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Textmagic Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderTextmagic') + ->label('sdk.description', '/docs/references/messaging/create-provider-textmagic.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('username', '', new Text(0), 'Textmagic username.') + ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'text-magic', + 'type' => 'sms', + 'credentials' => [ + 'username' => $username, + 'apiKey' => $apiKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/textmagic') - ->desc('Update Textmagic Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderTextmagic') - ->label('sdk.description', '/docs/references/messaging/update-provider-textmagic.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('username', '', new Text(0), 'Textmagic username.', true) - ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Textmagic Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderTextmagic') + ->label('sdk.description', '/docs/references/messaging/update-provider-textmagic.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('username', '', new Text(0), 'Textmagic username.', true) + ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'text-magic') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($username || $apiKey) { - // Check if all five variables are present - if ($username && $apiKey) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'apiKey' => $apiKey - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'text-magic') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($username || $apiKey) { + // Check if all five variables are present + if ($username && $apiKey) { + $provider->setAttribute('credentials', [ + 'username' => $username, + 'apiKey' => $apiKey, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::post('/v1/messaging/providers/twilio') - ->desc('Create Twilio Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderTwilio') - ->label('sdk.description', '/docs/references/messaging/create-provider-twilio.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') - ->param('authToken', '', new Text(0), 'Twilio authentication token.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'twilio', - 'type' => 'sms', - 'credentials' => [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Twilio Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderTwilio') + ->label('sdk.description', '/docs/references/messaging/create-provider-twilio.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') + ->param('authToken', '', new Text(0), 'Twilio authentication token.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'twilio', + 'type' => 'sms', + 'credentials' => [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/twilio') - ->desc('Update Twilio Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderTwilio') - ->label('sdk.description', '/docs/references/messaging/update-provider-twilio.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) - ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Twilio Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderTwilio') + ->label('sdk.description', '/docs/references/messaging/update-provider-twilio.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) + ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'twilio') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($accountSid || $authToken) { - // Check if all five variables are present - if ($accountSid && $authToken) { - $provider->setAttribute('credentials', [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'twilio') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($accountSid || $authToken) { + // Check if all five variables are present + if ($accountSid && $authToken) { + $provider->setAttribute('credentials', [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::post('/v1/messaging/providers/vonage') - ->desc('Create Vonage Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderVonage') - ->label('sdk.description', '/docs/references/messaging/create-provider-vonage.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('apiKey', '', new Text(0), 'Vonage API key.') - ->param('apiSecret', '', new Text(0), 'Vonage API secret.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'vonage', - 'type' => 'sms', - 'credentials' => [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create Vonage Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderVonage') + ->label('sdk.description', '/docs/references/messaging/create-provider-vonage.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('apiKey', '', new Text(0), 'Vonage API key.') + ->param('apiSecret', '', new Text(0), 'Vonage API secret.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'vonage', + 'type' => 'sms', + 'credentials' => [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/vonage') - ->desc('Update Vonage Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderVonage') - ->label('sdk.description', '/docs/references/messaging/update-provider-vonage.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('apiKey', '', new Text(0), 'Vonage API key.', true) - ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update Vonage Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderVonage') + ->label('sdk.description', '/docs/references/messaging/update-provider-vonage.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('apiKey', '', new Text(0), 'Vonage API key.', true) + ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'vonage') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($apiKey || $apiSecret) { - // Check if all five variables are present - if ($apiKey && $apiSecret) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'vonage') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($apiKey || $apiSecret) { + // Check if all five variables are present + if ($apiKey && $apiSecret) { + $provider->setAttribute('credentials', [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); /** * Push Providers */ App::post('/v1/messaging/providers/fcm') - ->desc('Create FCM Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderFCM') - ->label('sdk.description', '/docs/references/messaging/create-provider-fcm.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('serverKey', '', new Text(0), 'FCM Server Key.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'fcm', - 'type' => 'push', - 'credentials' => [ - 'serverKey' => $serverKey, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create FCM Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderFCM') + ->label('sdk.description', '/docs/references/messaging/create-provider-fcm.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('serverKey', '', new Text(0), 'FCM Server Key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $serverKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'fcm', + 'type' => 'push', + 'credentials' => [ + 'serverKey' => $serverKey, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/fcm') - ->desc('Update FCM Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderFCM') - ->label('sdk.description', '/docs/references/messaging/update-provider-fcm.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update FCM Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderFCM') + ->label('sdk.description', '/docs/references/messaging/update-provider-fcm.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + $providerAttr = $provider->getAttribute('provider'); - if ($providerAttr !== 'fcm') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } + if ($providerAttr !== 'fcm') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - if ($name) { - $provider->setAttribute('name', $name); - } + if ($name) { + $provider->setAttribute('name', $name); + } - if ($serverKey) { - $provider->setAttribute('credentials', ['serverKey' => $serverKey]); - } + if ($serverKey) { + $provider->setAttribute('credentials', ['serverKey' => $serverKey]); + } - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::post('/v1/messaging/providers/apns') - ->desc('Create APNS Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderAPNS') - ->label('sdk.description', '/docs/references/messaging/create-provider-apns.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('name', '', new Text(128), 'Provider name.') - ->param('authKey', '', new Text(0), 'APNS authentication key.') - ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') - ->param('teamId', '', new Text(0), 'APNS team ID.') - ->param('bundleId', '', new Text(0), 'APNS bundle ID.') - ->param('endpoint', '', new Text(0), 'APNS endpoint.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ - 'name' => $name, - 'provider' => 'apns', - 'type' => 'push', - 'credentials' => [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ], - ])); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + ->desc('Create APNS Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createProviderAPNS') + ->label('sdk.description', '/docs/references/messaging/create-provider-apns.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('name', '', new Text(128), 'Provider name.') + ->param('authKey', '', new Text(0), 'APNS authentication key.') + ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') + ->param('teamId', '', new Text(0), 'APNS team ID.') + ->param('bundleId', '', new Text(0), 'APNS bundle ID.') + ->param('endpoint', '', new Text(0), 'APNS endpoint.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $provider = $dbForProject->createDocument('providers', new Document([ + 'name' => $name, + 'provider' => 'apns', + 'type' => 'push', + 'credentials' => [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ], + ])); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::patch('/v1/messaging/providers/:id/apns') - ->desc('Update APNS Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderAPNS') - ->label('sdk.description', '/docs/references/messaging/update-provider-apns.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('authKey', '', new Text(0), 'APNS authentication key.', true) - ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) - ->param('teamId', '', new Text(0), 'APNS team ID.', true) - ->param('bundleId', '', new Text(0), 'APNS bundle ID.', true) - ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Update APNS Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderAPNS') + ->label('sdk.description', '/docs/references/messaging/update-provider-apns.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('authKey', '', new Text(0), 'APNS authentication key.', true) + ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) + ->param('teamId', '', new Text(0), 'APNS team ID.', true) + ->param('bundleId', '', new Text(0), 'APNS bundle ID.', true) + ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - $providerAttr = $provider->getAttribute('provider'); - - if ($providerAttr !== 'apns') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); - } - - if ($name) { - $provider->setAttribute('name', $name); - } - - if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { - // Check if all five variables are present - if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { - $provider->setAttribute('credentials', [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); } - } + $providerAttr = $provider->getAttribute('provider'); - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); + if ($providerAttr !== 'apns') { + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + } - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); + if ($name) { + $provider->setAttribute('name', $name); + } + + if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { + // Check if all five variables are present + if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { + $provider->setAttribute('credentials', [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ]); + } else { + // Not all credential params are present + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); App::delete('/v1/messaging/providers/:id') - ->desc('Delete Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.delete') - ->label('audits.resource', 'providers/{request.id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteProvider') - ->label('sdk.description', '/docs/references/messaging/delete-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('id', '', new UID(), 'Provider ID.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->desc('Delete Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.delete') + ->label('audits.resource', 'providers/{request.id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'deleteProvider') + ->label('sdk.description', '/docs/references/messaging/delete-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_NONE) + ->param('id', '', new UID(), 'Provider ID.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $dbForProject->deleteCachedDocument('providers', $provider->getId()); - $dbForProject->deleteDocument('providers', $provider->getId()); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + $dbForProject->deleteDocument('providers', $provider->getId()); - $response->noContent(); - }); + $response->noContent(); + }); App::post('/v1/messaging/messages/email') - ->desc('Send an email.') - ->groups(['api', 'messaging']) - ->label('audits.event', 'messages.create') - ->label('audits.resource', 'messages/{response.$id}') - ->label('scope', 'messages.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'sendEmail') - ->label('sdk.description', '/docs/references/messaging/send-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) - ->param('providerId', '', new Text(128), 'Email Provider ID.') - ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.', true) - ->param('subject', null, new Text(0), 'Email Subject.', true) - ->param('content', null, new Text(0), 'Email Content.', true) - ->param('from', null, new Text(0), 'Email from.', false) - ->param('html', null, new Text(0), 'Is content of type HTML', false) - ->param('deliveryTime', null, new Datetime(), 'Delivery time of the message', false) - ->inject('dbForProject') - ->inject('events') - ->inject('response') - ->action(function (string $providerId, string $to, string $subject, string $content, string $from, string $html, DateTime $deliveryTime, Database $dbForProject, Event $eventsInstance, Response $response) { - $provider = $dbForProject->getDocument('providers', $providerId); + ->desc('Send an email.') + ->groups(['api', 'messaging']) + ->label('audits.event', 'messages.create') + ->label('audits.resource', 'messages/{response.$id}') + ->label('scope', 'messages.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'sendEmail') + ->label('sdk.description', '/docs/references/messaging/send-email.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->param('providerId', '', new Text(128), 'Email Provider ID.') + ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.', true) + ->param('subject', null, new Text(0), 'Email Subject.', true) + ->param('content', null, new Text(0), 'Email Content.', true) + ->param('from', null, new Text(0), 'Email from.', false) + ->param('html', null, new Text(0), 'Is content of type HTML', false) + ->param('deliveryTime', null, new Datetime(), 'Delivery time of the message', false) + ->inject('dbForProject') + ->inject('events') + ->inject('response') + ->action(function (string $providerId, string $to, string $subject, string $content, string $from, string $html, DateTime $deliveryTime, Database $dbForProject, Event $eventsInstance, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } - $message = $dbForProject->createDocument('messages', new Document([ - 'providerId' => $provider->getId(), - 'providerInternalId' => $provider->getInternalId(), - 'to' => $to, - 'data' => [ - 'subject' => $subject, - 'content' => $content, - ], - 'deliveryTime' => $deliveryTime, - 'deliveryError' => null, - 'deliveredTo' => null, - 'delivered' => false, - 'search' => null, - ])); + $message = $dbForProject->createDocument('messages', new Document([ + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'to' => $to, + 'data' => [ + 'subject' => $subject, + 'content' => $content, + ], + 'deliveryTime' => $deliveryTime, + 'deliveryError' => null, + 'deliveredTo' => null, + 'delivered' => false, + 'search' => null, + ])); - $eventsInstance->setParam('messageId', $message->getId()); + $eventsInstance->setParam('messageId', $message->getId()); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_MESSAGE); - }); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_MESSAGE); + }); From a87745f685185ab9621cb54f816b03887ba56170 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 24 Aug 2023 15:37:59 +0530 Subject: [PATCH 25/72] fix tests --- tests/e2e/Services/Account/AccountBase.php | 3 +- .../Account/AccountCustomClientTest.php | 131 ++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index c611b6e920..6e039b509a 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -359,11 +359,10 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); - $this->assertEquals($response['headers']['status-code'], 200); $this->assertIsArray($response['body']['logs']); $this->assertNotEmpty($response['body']['logs']); - $this->assertCount(5, $response['body']['logs']); + $this->assertCount(3, $response['body']['logs']); $this->assertIsNumeric($response['body']['total']); $this->assertContains($response['body']['logs'][1]['event'], ["session.create"]); $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 39fa8d0fa5..6dce5d8f59 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -1205,4 +1205,135 @@ class AccountCustomClientTest extends Scope return $data; } + + /** + * @depends testCreateAccountSession + */ + public function testGetAccountLogs($data): array + { + sleep(10); + $session = $data['session'] ?? ''; + $sessionId = $data['sessionId'] ?? ''; + $userId = $data['id'] ?? ''; + /** + * Test for SUCCESS + */ + $response = $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, + ])); + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertIsArray($response['body']['logs']); + $this->assertNotEmpty($response['body']['logs']); + $this->assertCount(5, $response['body']['logs']); + $this->assertIsNumeric($response['body']['total']); + $this->assertContains($response['body']['logs'][1]['event'], ["targets.create"]); + $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][1]['time'])); + + $this->assertEquals('Windows', $response['body']['logs'][1]['osName']); + $this->assertEquals('WIN', $response['body']['logs'][1]['osCode']); + $this->assertEquals('10', $response['body']['logs'][1]['osVersion']); + + $this->assertEquals('browser', $response['body']['logs'][1]['clientType']); + $this->assertEquals('Chrome', $response['body']['logs'][1]['clientName']); + $this->assertEquals('CH', $response['body']['logs'][1]['clientCode']); + $this->assertEquals('70.0', $response['body']['logs'][1]['clientVersion']); + $this->assertEquals('Blink', $response['body']['logs'][1]['clientEngine']); + + $this->assertEquals('desktop', $response['body']['logs'][1]['deviceName']); + $this->assertEquals('', $response['body']['logs'][1]['deviceBrand']); + $this->assertEquals('', $response['body']['logs'][1]['deviceModel']); + $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); + + $this->assertEquals('--', $response['body']['logs'][1]['countryCode']); + $this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']); + + $this->assertContains($response['body']['logs'][2]['event'], ["session.create"]); + $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); + + $this->assertEquals('Windows', $response['body']['logs'][2]['osName']); + $this->assertEquals('WIN', $response['body']['logs'][2]['osCode']); + $this->assertEquals('10', $response['body']['logs'][2]['osVersion']); + + $this->assertEquals('browser', $response['body']['logs'][2]['clientType']); + $this->assertEquals('Chrome', $response['body']['logs'][2]['clientName']); + $this->assertEquals('CH', $response['body']['logs'][2]['clientCode']); + $this->assertEquals('70.0', $response['body']['logs'][2]['clientVersion']); + $this->assertEquals('Blink', $response['body']['logs'][2]['clientEngine']); + + $this->assertEquals('desktop', $response['body']['logs'][2]['deviceName']); + $this->assertEquals('', $response['body']['logs'][2]['deviceBrand']); + $this->assertEquals('', $response['body']['logs'][2]['deviceModel']); + $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); + + $this->assertEquals('--', $response['body']['logs'][2]['countryCode']); + $this->assertEquals('Unknown', $response['body']['logs'][2]['countryName']); + + $responseLimit = $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, + ]), [ + 'queries' => [ 'limit(1)' ], + ]); + + $this->assertEquals($responseLimit['headers']['status-code'], 200); + $this->assertIsArray($responseLimit['body']['logs']); + $this->assertNotEmpty($responseLimit['body']['logs']); + $this->assertCount(1, $responseLimit['body']['logs']); + $this->assertIsNumeric($responseLimit['body']['total']); + + $this->assertEquals($response['body']['logs'][0], $responseLimit['body']['logs'][0]); + + $responseOffset = $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, + ]), [ + 'queries' => [ 'offset(1)' ], + ]); + + $this->assertEquals($responseOffset['headers']['status-code'], 200); + $this->assertIsArray($responseOffset['body']['logs']); + $this->assertNotEmpty($responseOffset['body']['logs']); + $this->assertCount(4, $responseOffset['body']['logs']); + $this->assertIsNumeric($responseOffset['body']['total']); + + $this->assertEquals($response['body']['logs'][1], $responseOffset['body']['logs'][0]); + + $responseLimitOffset = $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, + ]), [ + 'queries' => [ 'limit(1)', 'offset(1)' ], + ]); + + $this->assertEquals($responseLimitOffset['headers']['status-code'], 200); + $this->assertIsArray($responseLimitOffset['body']['logs']); + $this->assertNotEmpty($responseLimitOffset['body']['logs']); + $this->assertCount(1, $responseLimitOffset['body']['logs']); + $this->assertIsNumeric($responseLimitOffset['body']['total']); + + $this->assertEquals($response['body']['logs'][1], $responseLimitOffset['body']['logs'][0]); + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals($response['headers']['status-code'], 401); + + return $data; + } } From df77f92860fc61683777007f0666e766c4e1773d Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 01:22:16 +0530 Subject: [PATCH 26/72] adds sub query for targets and topics, permission for user target --- app/config/collections.php | 60 +++++++++++++-------------------- app/controllers/api/account.php | 2 +- app/controllers/api/users.php | 5 +-- app/init.php | 47 ++++++++++++++++++++++---- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index c9005f8217..f066c38c70 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1664,6 +1664,17 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => ['subQueryTargets'], + ] ], 'indexes' => [ [ @@ -1702,28 +1713,6 @@ $commonCollections = [ '$id' => ID::custom('subscribers'), 'name' => 'Subscribers', 'attributes' => [ - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => ID::custom('targetId'), 'type' => Database::VAR_STRING, @@ -1770,20 +1759,6 @@ $commonCollections = [ ], ], 'indexes' => [ - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], [ '$id' => ID::custom('_key_targetId'), 'type' => Database::INDEX_KEY, @@ -1886,6 +1861,17 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('topics'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => ['subQueryTopics'], + ] ], 'indexes' => [ [ @@ -1924,7 +1910,7 @@ $commonCollections = [ 'orders' => [], ], ], - ] + ], ]; $projectCollections = array_merge([ diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 44a3bb9740..efcef85b68 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3038,7 +3038,7 @@ App::post('/v1/account/targets') $target = $dbForProject->createDocument('targets', new Document([ '$id' => $targetId, '$permissions' => [ - Permission::read(Role::user($user->getId())), + Permission::read(Role::any()), Permission::update(Role::user($user->getId())), Permission::delete(Role::user($user->getId())), ], diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index e7affffdc0..5218057018 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -414,9 +414,10 @@ App::post('/v1/users/:userId/targets') $target = $dbForProject->createDocument('targets', new Document([ '$id' => $targetId, - // TO DO: what permissions should be given when created a target. '$permissions' => [ - Permission::read(Role::any()) + Permission::read(Role::any()), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), diff --git a/app/init.php b/app/init.php index 09b383c3a0..a71df23bf0 100644 --- a/app/init.php +++ b/app/init.php @@ -542,12 +542,13 @@ Database::addFilter( return null; }, function (mixed $value, Document $document, Database $database) { - $provider = Authorization::skip(fn() => $database - ->findOne('providers', [ - Query::equal('$id', [$document->getAttribute('providerId')]), - Query::select(['type']), - Query::limit(APP_LIMIT_SUBQUERY), - ])); + $provider = Authorization::skip(fn () => $database + ->getDocument( + 'providers', + $document->getAttribute('providerId'), + [Query::select(['type'])] + ) + ); if ($provider) { return $provider->getAttribute('type'); } @@ -555,6 +556,40 @@ Database::addFilter( } ); +Database::addFilter( + 'subQueryTopics', + function (mixed $value) { + return null; + }, + function (mixed $value, Document $document, Database $database) { + $topicIds = Authorization::skip(fn () => \array_map( + fn ($document) => $document->getAttribute('topicId'), $database + ->find('subscribers', [ + Query::equal('targetInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])) + ); + return $database->find('topics', [Query::equal('$id', $topicIds)]); + } +); + +Database::addFilter( + 'subQueryTargets', + function (mixed $value) { + return null; + }, + function (mixed $value, Document $document, Database $database) { + $targetIds = Authorization::skip(fn () => \array_map( + fn ($document) => $document->getAttribute('targetId'), $database + ->find('subscribers', [ + Query::equal('topicInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])) + ); + return $database->find('targets', [Query::equal('$id', $targetIds)]); + } +); + /** * DB Formats */ From 33f4bd6ac453ebbe0b26e2074e48dc6e9a05a5e4 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 02:32:51 +0530 Subject: [PATCH 27/72] adds custom id for provider controlers, fixes subquery --- app/controllers/api/messaging.php | 121 +++++++++++++++--- app/init.php | 10 +- .../Messaging/MessagingServerTest.php | 13 +- 3 files changed, 122 insertions(+), 22 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 753abc8432..c08d772ef4 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2,11 +2,15 @@ use Appwrite\Event\Event; use Appwrite\Extend\Exception; +use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Providers; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime; @@ -96,13 +100,22 @@ App::post('/v1/messaging/providers/mailgun') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $apiKey, string $domain, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'mailgun', 'type' => 'email', @@ -184,12 +197,21 @@ App::post('/v1/messaging/providers/sendgrid') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Sendgrid API key.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $apiKey, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'sendgrid', 'type' => 'email', @@ -265,13 +287,22 @@ App::post('/v1/messaging/providers/msg91') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $senderId, string $authKey, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'msg91', 'type' => 'sms', @@ -353,13 +384,22 @@ App::post('/v1/messaging/providers/telesign') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('username', '', new Text(0), 'Telesign username.') ->param('password', '', new Text(0), 'Telesign password.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $username, string $password, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'telesign', 'type' => 'sms', @@ -441,13 +481,22 @@ App::post('/v1/messaging/providers/textmagic') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('username', '', new Text(0), 'Textmagic username.') ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $username, string $apiKey, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'text-magic', 'type' => 'sms', @@ -529,13 +578,22 @@ App::post('/v1/messaging/providers/twilio') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') ->param('authToken', '', new Text(0), 'Twilio authentication token.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $accountSid, string $authToken, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'twilio', 'type' => 'sms', @@ -617,13 +675,22 @@ App::post('/v1/messaging/providers/vonage') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Vonage API key.') ->param('apiSecret', '', new Text(0), 'Vonage API secret.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'vonage', 'type' => 'sms', @@ -708,12 +775,21 @@ App::post('/v1/messaging/providers/fcm') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('serverKey', '', new Text(0), 'FCM Server Key.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $serverKey, Document $user, Database $dbForProject, Response $response) { +$id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'fcm', 'type' => 'push', @@ -784,16 +860,25 @@ App::post('/v1/messaging/providers/apns') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('authKey', '', new Text(0), 'APNS authentication key.') ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') ->param('teamId', '', new Text(0), 'APNS team ID.') ->param('bundleId', '', new Text(0), 'APNS bundle ID.') ->param('endpoint', '', new Text(0), 'APNS endpoint.') + ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->createDocument('providers', new Document([ + ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Document $user, Database $dbForProject, Response $response) { + $id = $id == 'unique()' ? ID::unique() : $id; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $id, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], 'name' => $name, 'provider' => 'apns', 'type' => 'push', diff --git a/app/init.php b/app/init.php index a71df23bf0..0b5b75ee92 100644 --- a/app/init.php +++ b/app/init.php @@ -569,7 +569,10 @@ Database::addFilter( Query::limit(APP_LIMIT_SUBQUERY), ])) ); - return $database->find('topics', [Query::equal('$id', $topicIds)]); + if (\count($topicIds) > 0) { + return $database->find('topics', [Query::equal('$id', $topicIds)]); + } + return []; } ); @@ -586,7 +589,10 @@ Database::addFilter( Query::limit(APP_LIMIT_SUBQUERY), ])) ); - return $database->find('targets', [Query::equal('$id', $targetIds)]); + if (\count($targetIds) > 0) { + return $database->find('targets', [Query::equal('$id', $targetIds)]); + } + return []; } ); diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 7b93ab29ac..0724b6dd2c 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -16,44 +16,53 @@ class MessagingServerTest extends Scope { $providersParams = [ 'sendgrid' => [ + 'id' => 'unique()', 'name' => 'Sengrid1', 'apiKey' => 'my-apikey', ], 'mailgun' => [ + 'id' => 'unique()', 'name' => 'Mailgun1', 'apiKey' => 'my-apikey', 'domain' => 'my-domain', ], 'twilio' => [ + 'id' => 'unique()', 'name' => 'Twilio1', 'accountSid' => 'my-accountSid', 'authToken' => 'my-authToken', ], 'telesign' => [ + 'id' => 'unique()', 'name' => 'Telesign1', 'username' => 'my-username', 'password' => 'my-password', ], 'textmagic' => [ + 'id' => 'unique()', 'name' => 'Textmagic1', 'username' => 'my-username', 'apiKey' => 'my-apikey', ], 'msg91' => [ + 'id' => 'unique()', 'name' => 'Ms91-1', 'senderId' => 'my-senderid', 'authKey' => 'my-authkey', ], 'vonage' => [ + 'id' => 'unique()', 'name' => 'Vonage1', 'apiKey' => 'my-apikey', 'apiSecret' => 'my-apisecret', ], 'fcm' => [ + 'id' => 'unique()', 'name' => 'FCM1', 'serverKey' => 'my-serverkey', ], 'apns' => [ + 'id' => 'unique()', 'name' => 'APNS1', 'authKey' => 'my-authkey', 'authKeyId' => 'my-authkeyid', @@ -65,11 +74,11 @@ class MessagingServerTest extends Scope $providers = []; foreach (\array_keys($providersParams) as $key) { - $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, [ + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], - ], $providersParams[$key]); + ],$this->getHeaders()), $providersParams[$key]); \array_push($providers, $response['body']); $this->assertEquals(201, $response['headers']['status-code']); $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); From 048e8e81ba3ae59a2152ddad58ade4f3cdcc4107 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 02:59:06 +0530 Subject: [PATCH 28/72] removes permission from provider controllers --- app/controllers/api/messaging.php | 90 ++++--------------- .../Messaging/MessagingServerTest.php | 5 +- 2 files changed, 20 insertions(+), 75 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index c08d772ef4..f391eef5ba 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -104,19 +104,13 @@ App::post('/v1/messaging/providers/mailgun') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $domain, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'mailgun', 'type' => 'email', 'credentials' => [ @@ -200,19 +194,13 @@ App::post('/v1/messaging/providers/sendgrid') ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Sendgrid API key.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'sendgrid', 'type' => 'email', 'credentials' => [ @@ -291,19 +279,13 @@ App::post('/v1/messaging/providers/msg91') ->param('name', '', new Text(128), 'Provider name.') ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $senderId, string $authKey, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'msg91', 'type' => 'sms', 'credentials' => [ @@ -388,19 +370,13 @@ App::post('/v1/messaging/providers/telesign') ->param('name', '', new Text(128), 'Provider name.') ->param('username', '', new Text(0), 'Telesign username.') ->param('password', '', new Text(0), 'Telesign password.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $username, string $password, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'telesign', 'type' => 'sms', 'credentials' => [ @@ -485,19 +461,13 @@ App::post('/v1/messaging/providers/textmagic') ->param('name', '', new Text(128), 'Provider name.') ->param('username', '', new Text(0), 'Textmagic username.') ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $username, string $apiKey, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'text-magic', 'type' => 'sms', 'credentials' => [ @@ -582,19 +552,13 @@ App::post('/v1/messaging/providers/twilio') ->param('name', '', new Text(128), 'Provider name.') ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') ->param('authToken', '', new Text(0), 'Twilio authentication token.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $accountSid, string $authToken, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'twilio', 'type' => 'sms', 'credentials' => [ @@ -679,19 +643,13 @@ App::post('/v1/messaging/providers/vonage') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Vonage API key.') ->param('apiSecret', '', new Text(0), 'Vonage API secret.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'vonage', 'type' => 'sms', 'credentials' => [ @@ -778,19 +736,13 @@ App::post('/v1/messaging/providers/fcm') ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('serverKey', '', new Text(0), 'FCM Server Key.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $serverKey, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'fcm', 'type' => 'push', 'credentials' => [ @@ -867,19 +819,13 @@ App::post('/v1/messaging/providers/apns') ->param('teamId', '', new Text(0), 'APNS team ID.') ->param('bundleId', '', new Text(0), 'APNS bundle ID.') ->param('endpoint', '', new Text(0), 'APNS endpoint.') - ->inject('user') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Document $user, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { $id = $id == 'unique()' ? ID::unique() : $id; $provider = $dbForProject->createDocument('providers', new Document([ '$id' => $id, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'name' => $name, + 'name' => $name, 'provider' => 'apns', 'type' => 'push', 'credentials' => [ diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingServerTest.php index 0724b6dd2c..74855bc4a6 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingServerTest.php @@ -5,12 +5,12 @@ namespace Tests\E2E\Services\Messaging; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\SideConsole; +use Tests\E2E\Scopes\SideServer; class MessagingServerTest extends Scope { use ProjectCustom; - use SideConsole; + use SideServer; public function testCreateProviders(): array { @@ -77,7 +77,6 @@ class MessagingServerTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], ],$this->getHeaders()), $providersParams[$key]); \array_push($providers, $response['body']); $this->assertEquals(201, $response['headers']['status-code']); From 596066606831630ed0b237eb11ee958de89074c1 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 03:09:12 +0530 Subject: [PATCH 29/72] added messaging base test --- ...{MessagingServerTest.php => MessagingBase.php} | 15 +++++---------- .../Messaging/MessagingCustomServerTest.php | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) rename tests/e2e/Services/Messaging/{MessagingServerTest.php => MessagingBase.php} (95%) create mode 100644 tests/e2e/Services/Messaging/MessagingCustomServerTest.php diff --git a/tests/e2e/Services/Messaging/MessagingServerTest.php b/tests/e2e/Services/Messaging/MessagingBase.php similarity index 95% rename from tests/e2e/Services/Messaging/MessagingServerTest.php rename to tests/e2e/Services/Messaging/MessagingBase.php index 74855bc4a6..8a0937c0eb 100644 --- a/tests/e2e/Services/Messaging/MessagingServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -3,16 +3,10 @@ namespace Tests\E2E\Services\Messaging; use Tests\E2E\Client; -use Tests\E2E\Scopes\ProjectCustom; -use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\SideServer; -class MessagingServerTest extends Scope +trait MessagingBase { - use ProjectCustom; - use SideServer; - - public function testCreateProviders(): array + public function testCreateProviders(): array { $providersParams = [ 'sendgrid' => [ @@ -77,7 +71,8 @@ class MessagingServerTest extends Scope $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ],$this->getHeaders()), $providersParams[$key]); + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), $providersParams[$key]); \array_push($providers, $response['body']); $this->assertEquals(201, $response['headers']['status-code']); $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); @@ -195,4 +190,4 @@ class MessagingServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } } -} +} \ No newline at end of file diff --git a/tests/e2e/Services/Messaging/MessagingCustomServerTest.php b/tests/e2e/Services/Messaging/MessagingCustomServerTest.php new file mode 100644 index 0000000000..c126df3261 --- /dev/null +++ b/tests/e2e/Services/Messaging/MessagingCustomServerTest.php @@ -0,0 +1,15 @@ + Date: Fri, 25 Aug 2023 04:43:40 +0530 Subject: [PATCH 30/72] changes id to providerId for provider create controllers --- app/controllers/api/messaging.php | 74 +++++++++---------- .../e2e/Services/Messaging/MessagingBase.php | 20 ++--- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index f391eef5ba..d86b8247b4 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -56,7 +56,7 @@ App::get('/v1/messaging/providers') $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ 'total' => $dbForProject->count('providers', $filterQueries, APP_LIMIT_COUNT), - 'indexes' => $dbForProject->find('providers', $queries), + 'providers' => $dbForProject->find('providers', $queries), ]), Response::MODEL_PROVIDER_LIST); }); @@ -100,16 +100,16 @@ App::post('/v1/messaging/providers/mailgun') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'mailgun', 'type' => 'email', @@ -191,15 +191,15 @@ App::post('/v1/messaging/providers/sendgrid') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Sendgrid API key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $apiKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'sendgrid', 'type' => 'email', @@ -275,16 +275,16 @@ App::post('/v1/messaging/providers/msg91') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'msg91', 'type' => 'sms', @@ -366,16 +366,16 @@ App::post('/v1/messaging/providers/telesign') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('username', '', new Text(0), 'Telesign username.') ->param('password', '', new Text(0), 'Telesign password.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $username, string $password, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'telesign', 'type' => 'sms', @@ -457,16 +457,16 @@ App::post('/v1/messaging/providers/textmagic') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('username', '', new Text(0), 'Textmagic username.') ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'text-magic', 'type' => 'sms', @@ -548,16 +548,16 @@ App::post('/v1/messaging/providers/twilio') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') ->param('authToken', '', new Text(0), 'Twilio authentication token.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'twilio', 'type' => 'sms', @@ -639,16 +639,16 @@ App::post('/v1/messaging/providers/vonage') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Vonage API key.') ->param('apiSecret', '', new Text(0), 'Vonage API secret.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'vonage', 'type' => 'sms', @@ -733,15 +733,15 @@ App::post('/v1/messaging/providers/fcm') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('serverKey', '', new Text(0), 'FCM Server Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { -$id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $serverKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'fcm', 'type' => 'push', @@ -812,7 +812,7 @@ App::post('/v1/messaging/providers/apns') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('authKey', '', new Text(0), 'APNS authentication key.') ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') @@ -821,10 +821,10 @@ App::post('/v1/messaging/providers/apns') ->param('endpoint', '', new Text(0), 'APNS endpoint.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $id = $id == 'unique()' ? ID::unique() : $id; + ->action(function (string $providerId, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $id, + '$id' => $providerId, 'name' => $name, 'provider' => 'apns', 'type' => 'push', diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 8a0937c0eb..0bea95ac1a 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -10,53 +10,53 @@ trait MessagingBase { $providersParams = [ 'sendgrid' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Sengrid1', 'apiKey' => 'my-apikey', ], 'mailgun' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Mailgun1', 'apiKey' => 'my-apikey', 'domain' => 'my-domain', ], 'twilio' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Twilio1', 'accountSid' => 'my-accountSid', 'authToken' => 'my-authToken', ], 'telesign' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Telesign1', 'username' => 'my-username', 'password' => 'my-password', ], 'textmagic' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Textmagic1', 'username' => 'my-username', 'apiKey' => 'my-apikey', ], 'msg91' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Ms91-1', 'senderId' => 'my-senderid', 'authKey' => 'my-authkey', ], 'vonage' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'Vonage1', 'apiKey' => 'my-apikey', 'apiSecret' => 'my-apisecret', ], 'fcm' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'FCM1', 'serverKey' => 'my-serverkey', ], 'apns' => [ - 'id' => 'unique()', + 'providerId' => 'unique()', 'name' => 'APNS1', 'authKey' => 'my-authkey', 'authKeyId' => 'my-authkeyid', @@ -159,7 +159,7 @@ trait MessagingBase 'x-appwrite-key' => $this->getProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(\count($providers), $response['body']['total']); + $this->assertEquals(\count($providers), \count($response['body']['providers'])); } /** From 9be0592dabab506f177ea5cf8a0e95d3ec95f5e2 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 04:46:15 +0530 Subject: [PATCH 31/72] lint fix --- app/controllers/api/messaging.php | 94 +++++++++---------- app/init.php | 21 +++-- .../e2e/Services/Messaging/MessagingBase.php | 4 +- .../Messaging/MessagingCustomServerTest.php | 1 - 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index d86b8247b4..ef69cdc808 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -29,7 +29,7 @@ App::get('/v1/messaging/providers') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) - ->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('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) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, Database $dbForProject, Response $response) { @@ -107,10 +107,10 @@ App::post('/v1/messaging/providers/mailgun') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'mailgun', 'type' => 'email', 'credentials' => [ @@ -151,7 +151,7 @@ App::patch('/v1/messaging/providers/:id/mailgun') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'mailgun') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -197,10 +197,10 @@ App::post('/v1/messaging/providers/sendgrid') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $apiKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'sendgrid', 'type' => 'email', 'credentials' => [ @@ -239,7 +239,7 @@ App::patch('/v1/messaging/providers/:id/sendgrid') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'sendgrid') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -275,17 +275,17 @@ App::post('/v1/messaging/providers/msg91') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'msg91', 'type' => 'sms', 'credentials' => [ @@ -326,7 +326,7 @@ App::patch('/v1/messaging/providers/:id/msg91') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'msg91') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -373,10 +373,10 @@ App::post('/v1/messaging/providers/telesign') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $username, string $password, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'telesign', 'type' => 'sms', 'credentials' => [ @@ -417,7 +417,7 @@ App::patch('/v1/messaging/providers/:id/telesign') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'telesign') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -464,10 +464,10 @@ App::post('/v1/messaging/providers/textmagic') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'text-magic', 'type' => 'sms', 'credentials' => [ @@ -508,7 +508,7 @@ App::patch('/v1/messaging/providers/:id/textmagic') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'text-magic') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -555,10 +555,10 @@ App::post('/v1/messaging/providers/twilio') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'twilio', 'type' => 'sms', 'credentials' => [ @@ -599,7 +599,7 @@ App::patch('/v1/messaging/providers/:id/twilio') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'twilio') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -646,10 +646,10 @@ App::post('/v1/messaging/providers/vonage') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'vonage', 'type' => 'sms', 'credentials' => [ @@ -690,7 +690,7 @@ App::patch('/v1/messaging/providers/:id/vonage') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'vonage') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -739,10 +739,10 @@ App::post('/v1/messaging/providers/fcm') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $serverKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'fcm', 'type' => 'push', 'credentials' => [ @@ -781,7 +781,7 @@ App::patch('/v1/messaging/providers/:id/fcm') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'fcm') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { @@ -822,10 +822,10 @@ App::post('/v1/messaging/providers/apns') ->inject('dbForProject') ->inject('response') ->action(function (string $providerId, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ - '$id' => $providerId, - 'name' => $name, + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = $dbForProject->createDocument('providers', new Document([ + '$id' => $providerId, + 'name' => $name, 'provider' => 'apns', 'type' => 'push', 'credentials' => [ @@ -872,7 +872,7 @@ App::patch('/v1/messaging/providers/:id/apns') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'apns') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE.$providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } if ($name) { diff --git a/app/init.php b/app/init.php index 0b5b75ee92..57d99dac83 100644 --- a/app/init.php +++ b/app/init.php @@ -544,11 +544,10 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { $provider = Authorization::skip(fn () => $database ->getDocument( - 'providers', - $document->getAttribute('providerId'), + 'providers', + $document->getAttribute('providerId'), [Query::select(['type'])] - ) - ); + )); if ($provider) { return $provider->getAttribute('type'); } @@ -563,12 +562,13 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $topicIds = Authorization::skip(fn () => \array_map( - fn ($document) => $document->getAttribute('topicId'), $database + fn ($document) => $document->getAttribute('topicId'), + $database ->find('subscribers', [ Query::equal('targetInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), - ])) - ); + ]) + )); if (\count($topicIds) > 0) { return $database->find('topics', [Query::equal('$id', $topicIds)]); } @@ -583,12 +583,13 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $targetIds = Authorization::skip(fn () => \array_map( - fn ($document) => $document->getAttribute('targetId'), $database + fn ($document) => $document->getAttribute('targetId'), + $database ->find('subscribers', [ Query::equal('topicInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), - ])) - ); + ]) + )); if (\count($targetIds) > 0) { return $database->find('targets', [Query::equal('$id', $targetIds)]); } diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 0bea95ac1a..c460d2b5d3 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -6,7 +6,7 @@ use Tests\E2E\Client; trait MessagingBase { - public function testCreateProviders(): array + public function testCreateProviders(): array { $providersParams = [ 'sendgrid' => [ @@ -190,4 +190,4 @@ trait MessagingBase $this->assertEquals(204, $response['headers']['status-code']); } } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Messaging/MessagingCustomServerTest.php b/tests/e2e/Services/Messaging/MessagingCustomServerTest.php index c126df3261..19e0113364 100644 --- a/tests/e2e/Services/Messaging/MessagingCustomServerTest.php +++ b/tests/e2e/Services/Messaging/MessagingCustomServerTest.php @@ -11,5 +11,4 @@ class MessagingCustomServerTest extends Scope use MessagingBase; use ProjectCustom; use SideServer; - } From c59887e8fb26326e96ffed847cc19dfe79ab6be3 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 15:55:04 +0530 Subject: [PATCH 32/72] fixes issue in sub queries --- app/config/collections.php | 22 ++------------------ app/init.php | 22 +------------------- tests/e2e/Services/Users/UsersBase.php | 28 ++++++++++---------------- 3 files changed, 14 insertions(+), 58 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index f066c38c70..d7f6a6601c 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1673,7 +1673,7 @@ $commonCollections = [ 'required' => false, 'default' => null, 'array' => true, - 'filters' => ['subQueryTargets'], + 'filters' => ['subQueryTopicTargets'], ] ], 'indexes' => [ @@ -1861,17 +1861,6 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], - [ - '$id' => ID::custom('topics'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => ['subQueryTopics'], - ] ], 'indexes' => [ [ @@ -1901,14 +1890,7 @@ $commonCollections = [ 'attributes' => ['providerInternalId'], 'lengths' => [], 'orders' => [], - ], - [ - '$id' => ID::custom('_key_providerType'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerType'], - 'lengths' => [], - 'orders' => [], - ], + ] ], ], ]; diff --git a/app/init.php b/app/init.php index 57d99dac83..eed61f2eeb 100644 --- a/app/init.php +++ b/app/init.php @@ -555,29 +555,9 @@ Database::addFilter( } ); -Database::addFilter( - 'subQueryTopics', - function (mixed $value) { - return null; - }, - function (mixed $value, Document $document, Database $database) { - $topicIds = Authorization::skip(fn () => \array_map( - fn ($document) => $document->getAttribute('topicId'), - $database - ->find('subscribers', [ - Query::equal('targetInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ]) - )); - if (\count($topicIds) > 0) { - return $database->find('topics', [Query::equal('$id', $topicIds)]); - } - return []; - } -); Database::addFilter( - 'subQueryTargets', + 'subQueryTopicTargets', function (mixed $value) { return null; }, diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 947a3a5cd9..923eb35adf 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -1216,11 +1216,11 @@ trait UsersBase */ public function testCreateUserTarget(array $data): array { - $provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', [ + $provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ], [ + ], $this->getHeaders()), [ + 'providerId' => 'unique()', 'name' => 'Sengrid1', 'apiKey' => 'my-apikey' ]); @@ -1228,8 +1228,7 @@ trait UsersBase $response = $this->client->call(Client::METHOD_POST, '/users/' . $data['userId'] . '/targets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ]), [ + ], $this->getHeaders()), [ 'targetId' => ID::unique(), 'providerId' => $provider['body']['$id'], 'identifier' => 'my-token', @@ -1248,8 +1247,7 @@ trait UsersBase $response = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/targets/' . $data['$id'] . '/identifier', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ]), [ + ], $this->getHeaders()), [ 'identifier' => 'my-updated-token', ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -1258,17 +1256,16 @@ trait UsersBase } /** - * @depends testGetUser + * @depends testUpdateUserTarget */ public function testListUserTarget(array $data) { $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); + ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, $response['body']['total']); + $this->assertEquals(1, \count($response['body']['targets'])); } /** @@ -1279,8 +1276,7 @@ trait UsersBase $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets/' . $data['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); + ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($data['$id'], $response['body']['$id']); } @@ -1293,14 +1289,12 @@ trait UsersBase $response = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'] . '/targets/' . $data['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); + ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/targets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); + ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(0, $response['body']['total']); } From d7c85622607e7066bb76c2ea67eb823fd028c95e Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 16:02:46 +0530 Subject: [PATCH 33/72] removes target controllers from account service --- app/controllers/api/account.php | 194 ------------------ .../Account/AccountCustomClientTest.php | 112 ---------- 2 files changed, 306 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index efcef85b68..fecbf51d17 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1825,29 +1825,6 @@ App::get('/v1/account/logs') ]), Response::MODEL_LOG_LIST); }); -App::get('/v1/account/targets') - ->desc('List Account Targets') - ->groups(['api', 'account']) - ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listTargets') - ->label('sdk.description', '/docs/references/account/list-targets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET_LIST) - ->inject('user') - ->inject('response') - ->action(function (Document $user, Response $response) { - - $targets = $user->getAttribute('targets', []); - - $response->dynamic(new Document([ - 'targets' => $targets, - 'total' => \count($targets), - ]), Response::MODEL_TARGET_LIST); - }); - App::get('/v1/account/sessions/:sessionId') ->desc('Get Session') ->groups(['api', 'account']) @@ -1892,33 +1869,6 @@ App::get('/v1/account/sessions/:sessionId') throw new Exception(Exception::USER_SESSION_NOT_FOUND); }); -App::get('/v1/account/targets/:targetId') - ->desc('Get Target') - ->groups(['api', 'account']) - ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getTarget') - ->label('sdk.description', '/docs/references/account/get-Target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) - ->label('sdk.offline.model', '/account/targets') - ->label('sdk.offline.key', '{targetId}') - ->param('targetId', '', new UID(), 'Target ID.') - ->inject('user') - ->inject('response') - ->action(function (string $targetId, Document $user, Response $response) { - - $target = $user->find('$id', $targetId, 'targets'); - - if (empty($target)) { - throw new Exception(Exception::USER_TARGET_NOT_FOUND); - } - - $response->dynamic($target, Response::MODEL_TARGET); - }); - App::patch('/v1/account/name') ->desc('Update Name') ->groups(['api', 'account']) @@ -2999,147 +2949,3 @@ App::put('/v1/account/verification/phone') $response->dynamic($verificationDocument, Response::MODEL_TOKEN); }); - -App::post('/v1/account/targets') - ->desc('Create Account\'s Target') - ->groups(['api', 'account']) - ->label('event', 'users.[userId].targets.[targetId].create') - ->label('audits.event', 'targets.create') - ->label('audits.resource', 'user/{response.userId}') - ->label('audits.userId', '{response.userId}') - ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createTarget') - ->label('sdk.description', '/docs/references/account/create-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('targetId', '', new UID(), 'Target ID.') - ->param('providerId', '', new UID(), 'Provider ID.') - ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') - ->inject('user') - ->inject('response') - ->inject('dbForProject') - ->inject('events') - ->action(function (string $targetId, string $providerId, string $identifier, Document $user, Response $response, Database $dbForProject, Event $events) { - $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); - - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - - $target = $dbForProject->getDocument('targets', $targetId); - - if (!$target->isEmpty()) { - throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); - } - - $target = $dbForProject->createDocument('targets', new Document([ - '$id' => $targetId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'providerId' => $providerId, - 'providerInternalId' => $provider->getInternalId(), - 'providerType' => null, - 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), - 'identifier' => $identifier, - ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); - $events - ->setParam('userId', $user->getId()) - ->setParam('targetId', $targetId); - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($target, Response::MODEL_TARGET); - }); - -App::patch('/v1/account/targets/:targetId/identifier') - ->desc('Update account\'s target identifier') - ->groups(['api', 'account']) - ->label('event', 'users.[userId].targets.[targetId].update') - ->label('audits.event', 'targets.update') - ->label('audits.resource', 'user/{response.userId}') - ->label('audits.userId', '{response.userId}') - ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateTargetIdentifier') - ->label('sdk.description', '/docs/references/account/update-target-identifier.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) - ->param('targetId', '', new UID(), 'Target ID.') - ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') - ->inject('user') - ->inject('response') - ->inject('dbForProject') - ->inject('events') - ->action(function (string $targetId, string $identifier, Document $user, Response $response, Database $dbForProject, Event $events) { - - $target = $dbForProject->getDocument('targets', $targetId); - - if ($target->isEmpty()) { - throw new Exception(Exception::USER_TARGET_NOT_FOUND); - } - - // Update the target identifier here - $target->setAttribute('identifier', $identifier); - - $target = $dbForProject->updateDocument('targets', $target->getId(), $target); - $dbForProject->deleteCachedDocument('users', $user->getId()); - - $events - ->setParam('userId', $user->getId()) - ->setParam('targetId', $targetId); - - $response - ->dynamic($target, Response::MODEL_TARGET); - }); - -App::delete('/v1/account/targets/:targetId') - ->desc('Delete account\'s target') - ->groups(['api', 'account']) - ->label('event', 'users.[userId].targets.[targetId].delete') - ->label('audits.event', 'targets.delete') - ->label('audits.resource', 'user/{response.userId}') - ->label('audits.userId', '{response.userId}') - ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteTarget') - ->label('sdk.description', '/docs/references/account/delete-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('targetId', '', new UID(), 'Target ID.') - ->inject('user') - ->inject('response') - ->inject('dbForProject') - ->inject('events') - ->action(function (string $targetId, Document $user, Response $response, Database $dbForProject, Event $events) { - - $target = $dbForProject->getDocument('targets', $targetId); - - if ($target->isEmpty()) { - throw new Exception(Exception::USER_TARGET_NOT_FOUND); - } - - $target = $dbForProject->deleteDocument('targets', $target->getId()); - $dbForProject->deleteCachedDocument('users', $user->getId()); - $user = $dbForProject->getDocument('users', $user->getId()); - - // clone user object to send to workers - $clone = clone $user; - - $events - ->setParam('userId', $user->getId()) - ->setParam('targetId', $targetId) - ->setPayload($response->output($clone, Response::MODEL_USER)); - - $response->noContent(); - }); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 6dce5d8f59..d272605e58 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -116,118 +116,6 @@ class AccountCustomClientTest extends Scope return []; } - /** - * @depends testCreateAccountSession - */ - public function testCreateAccountTarget(array $data): array - { - $session = $data['session'] ?? ''; - $apiKey = $this->getProject()['apiKey']; - - $provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $apiKey, - ], [ - 'name' => 'Sengrid1', - 'apiKey' => 'my-apikey' - ]); - $this->assertEquals(201, $provider['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/account/targets', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ - 'targetId' => ID::unique(), - 'providerId' => $provider['body']['$id'], - 'identifier' => 'my-token', - ]); - $this->assertEquals(201, $response['headers']['status-code']); - $this->assertEquals($provider['body']['$id'], $response['body']['providerId']); - $this->assertEquals('my-token', $response['body']['identifier']); - return ['target' => $response['body'], 'session' => $session]; - } - - /** - * @depends testCreateAccountTarget - */ - public function testUpdateAccountTarget(array $data): array - { - $session = $data['session'] ?? ''; - $target = $data['target']; - $response = $this->client->call(Client::METHOD_PATCH, '/account/targets/' . $target['$id'] . '/identifier', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ - 'identifier' => 'my-updated-token', - ]); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals('my-updated-token', $response['body']['identifier']); - return $data; - } - - /** - * @depends testCreateAccountSession - */ - public function testListAccountTarget(array $data) - { - $session = $data['session'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/account/targets', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ])); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, $response['body']['total']); - } - - /** - * @depends testCreateAccountTarget - */ - public function testGetAccountTarget(array $data) - { - $session = $data['session'] ?? ''; - $target = $data['target']; - - $response = $this->client->call(Client::METHOD_GET, '/account/targets/' . $target['$id'], array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ])); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals($data['target']['$id'], $response['body']['$id']); - } - - /** - * @depends testUpdateAccountTarget - */ - public function testDeleteAccountTarget(array $data) - { - $session = $data['session'] ?? ''; - $target = $data['target']; - - $response = $this->client->call(Client::METHOD_DELETE, '/account/targets/' . $target['$id'], array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ])); - $this->assertEquals(204, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/account/targets', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ])); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(0, $response['body']['total']); - } - public function testBlockedAccount(): array { $email = uniqid() . 'user@localhost.test'; From 2c4e90d6608dec167688a18edf4732e4acc11d31 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 25 Aug 2023 19:48:21 +0530 Subject: [PATCH 34/72] removes unnecessary test case --- .../Account/AccountCustomClientTest.php | 131 ------------------ 1 file changed, 131 deletions(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index d272605e58..d225496a65 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -1093,135 +1093,4 @@ class AccountCustomClientTest extends Scope return $data; } - - /** - * @depends testCreateAccountSession - */ - public function testGetAccountLogs($data): array - { - sleep(10); - $session = $data['session'] ?? ''; - $sessionId = $data['sessionId'] ?? ''; - $userId = $data['id'] ?? ''; - /** - * Test for SUCCESS - */ - $response = $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, - ])); - $this->assertEquals($response['headers']['status-code'], 200); - $this->assertIsArray($response['body']['logs']); - $this->assertNotEmpty($response['body']['logs']); - $this->assertCount(5, $response['body']['logs']); - $this->assertIsNumeric($response['body']['total']); - $this->assertContains($response['body']['logs'][1]['event'], ["targets.create"]); - $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][1]['time'])); - - $this->assertEquals('Windows', $response['body']['logs'][1]['osName']); - $this->assertEquals('WIN', $response['body']['logs'][1]['osCode']); - $this->assertEquals('10', $response['body']['logs'][1]['osVersion']); - - $this->assertEquals('browser', $response['body']['logs'][1]['clientType']); - $this->assertEquals('Chrome', $response['body']['logs'][1]['clientName']); - $this->assertEquals('CH', $response['body']['logs'][1]['clientCode']); - $this->assertEquals('70.0', $response['body']['logs'][1]['clientVersion']); - $this->assertEquals('Blink', $response['body']['logs'][1]['clientEngine']); - - $this->assertEquals('desktop', $response['body']['logs'][1]['deviceName']); - $this->assertEquals('', $response['body']['logs'][1]['deviceBrand']); - $this->assertEquals('', $response['body']['logs'][1]['deviceModel']); - $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); - - $this->assertEquals('--', $response['body']['logs'][1]['countryCode']); - $this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']); - - $this->assertContains($response['body']['logs'][2]['event'], ["session.create"]); - $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); - - $this->assertEquals('Windows', $response['body']['logs'][2]['osName']); - $this->assertEquals('WIN', $response['body']['logs'][2]['osCode']); - $this->assertEquals('10', $response['body']['logs'][2]['osVersion']); - - $this->assertEquals('browser', $response['body']['logs'][2]['clientType']); - $this->assertEquals('Chrome', $response['body']['logs'][2]['clientName']); - $this->assertEquals('CH', $response['body']['logs'][2]['clientCode']); - $this->assertEquals('70.0', $response['body']['logs'][2]['clientVersion']); - $this->assertEquals('Blink', $response['body']['logs'][2]['clientEngine']); - - $this->assertEquals('desktop', $response['body']['logs'][2]['deviceName']); - $this->assertEquals('', $response['body']['logs'][2]['deviceBrand']); - $this->assertEquals('', $response['body']['logs'][2]['deviceModel']); - $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); - - $this->assertEquals('--', $response['body']['logs'][2]['countryCode']); - $this->assertEquals('Unknown', $response['body']['logs'][2]['countryName']); - - $responseLimit = $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, - ]), [ - 'queries' => [ 'limit(1)' ], - ]); - - $this->assertEquals($responseLimit['headers']['status-code'], 200); - $this->assertIsArray($responseLimit['body']['logs']); - $this->assertNotEmpty($responseLimit['body']['logs']); - $this->assertCount(1, $responseLimit['body']['logs']); - $this->assertIsNumeric($responseLimit['body']['total']); - - $this->assertEquals($response['body']['logs'][0], $responseLimit['body']['logs'][0]); - - $responseOffset = $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, - ]), [ - 'queries' => [ 'offset(1)' ], - ]); - - $this->assertEquals($responseOffset['headers']['status-code'], 200); - $this->assertIsArray($responseOffset['body']['logs']); - $this->assertNotEmpty($responseOffset['body']['logs']); - $this->assertCount(4, $responseOffset['body']['logs']); - $this->assertIsNumeric($responseOffset['body']['total']); - - $this->assertEquals($response['body']['logs'][1], $responseOffset['body']['logs'][0]); - - $responseLimitOffset = $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, - ]), [ - 'queries' => [ 'limit(1)', 'offset(1)' ], - ]); - - $this->assertEquals($responseLimitOffset['headers']['status-code'], 200); - $this->assertIsArray($responseLimitOffset['body']['logs']); - $this->assertNotEmpty($responseLimitOffset['body']['logs']); - $this->assertCount(1, $responseLimitOffset['body']['logs']); - $this->assertIsNumeric($responseLimitOffset['body']['total']); - - $this->assertEquals($response['body']['logs'][1], $responseLimitOffset['body']['logs'][0]); - /** - * Test for FAILURE - */ - $response = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ])); - - $this->assertEquals($response['headers']['status-code'], 401); - - return $data; - } } From 379f7b9aa2347ae77ecbacf1391e25697652f4d4 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Mon, 28 Aug 2023 20:41:47 +0530 Subject: [PATCH 35/72] fixes subquery attribute in collection config --- app/config/collections.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/collections.php b/app/config/collections.php index d7f6a6601c..626676259b 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1672,7 +1672,7 @@ $commonCollections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, + 'array' => false, 'filters' => ['subQueryTopicTargets'], ] ], From 112c7a5133c7acff3659c52f63ea38e4a037677e Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 29 Aug 2023 22:29:48 +0530 Subject: [PATCH 36/72] adds default attribute for providers --- app/config/collections.php | 11 ++ app/config/errors.php | 9 +- app/controllers/api/messaging.php | 221 ++++++++++++++++++++++++++---- src/Appwrite/Extend/Exception.php | 1 + 4 files changed, 211 insertions(+), 31 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 626676259b..92e732007f 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1444,6 +1444,17 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('default'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], [ '$id' => ID::custom('credentials'), 'type' => Database::VAR_STRING, diff --git a/app/config/errors.php b/app/config/errors.php index b4b2429f31..49ba9bc1a2 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -700,12 +700,17 @@ return [ /** Provider Errors */ Exception::PROVIDER_NOT_FOUND => [ 'name' => Exception::PROVIDER_NOT_FOUND, - 'description' => 'Provider with the request ID could not be found.', + 'description' => 'Provider with the requested ID could not be found.', 'code' => 404, ], + Exception::PROVIDER_ALREADY_EXISTS => [ + 'name' => Exception::PROVIDER_ALREADY_EXISTS, + 'description' => 'Provider with the requested ID already exists.', + 'code' => 409, + ], Exception::PROVIDER_INCORRECT_TYPE => [ 'name' => Exception::PROVIDER_INCORRECT_TYPE, - 'description' => 'Provider with the request ID is of incorrect type: ', + 'description' => 'Provider with the requested ID is of incorrect type: ', 'code' => 400, ] ]; diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index ef69cdc808..e91eb48fb7 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -8,14 +8,14 @@ use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime; use Utopia\Database\Validator\UID; use Utopia\Validator\ArrayList; +use Utopia\Validator\Boolean; use Utopia\Validator\Text; App::get('/v1/messaging/providers') @@ -102,22 +102,41 @@ App::post('/v1/messaging/providers/mailgun') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $apiKey, string $domain, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'mailgun', 'type' => 'email', + 'default' => $default, 'credentials' => [ 'apiKey' => $apiKey, 'domain' => $domain, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -193,20 +212,38 @@ App::post('/v1/messaging/providers/sendgrid') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('apiKey', '', new Text(0), 'Sendgrid API key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $apiKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'sendgrid', 'type' => 'email', + 'default' => $default, 'credentials' => [ 'apiKey' => $apiKey, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -277,22 +314,40 @@ App::post('/v1/messaging/providers/msg91') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $senderId, string $authKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'msg91', 'type' => 'sms', + 'default' => $default, 'credentials' => [ 'senderId' => $senderId, 'authKey' => $authKey, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -368,22 +423,40 @@ App::post('/v1/messaging/providers/telesign') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('username', '', new Text(0), 'Telesign username.') ->param('password', '', new Text(0), 'Telesign password.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $username, string $password, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $username, string $password, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'telesign', 'type' => 'sms', + 'default' => $default, 'credentials' => [ 'username' => $username, 'password' => $password, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -459,22 +532,40 @@ App::post('/v1/messaging/providers/textmagic') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('username', '', new Text(0), 'Textmagic username.') ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $username, string $apiKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'text-magic', 'type' => 'sms', + 'default' => $default, 'credentials' => [ 'username' => $username, 'apiKey' => $apiKey, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -550,22 +641,40 @@ App::post('/v1/messaging/providers/twilio') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') ->param('authToken', '', new Text(0), 'Twilio authentication token.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $accountSid, string $authToken, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'twilio', 'type' => 'sms', + 'default' => $default, 'credentials' => [ 'accountSid' => $accountSid, 'authToken' => $authToken, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -641,22 +750,40 @@ App::post('/v1/messaging/providers/vonage') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('apiKey', '', new Text(0), 'Vonage API key.') ->param('apiSecret', '', new Text(0), 'Vonage API secret.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'vonage', 'type' => 'sms', + 'default' => $default, 'credentials' => [ 'apiKey' => $apiKey, 'apiSecret' => $apiSecret, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -735,20 +862,38 @@ App::post('/v1/messaging/providers/fcm') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('serverKey', '', new Text(0), 'FCM Server Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $serverKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $serverKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'fcm', 'type' => 'push', + 'default' => $default, 'credentials' => [ 'serverKey' => $serverKey, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); @@ -814,6 +959,7 @@ App::post('/v1/messaging/providers/apns') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('authKey', '', new Text(0), 'APNS authentication key.') ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') ->param('teamId', '', new Text(0), 'APNS team ID.') @@ -821,13 +967,14 @@ App::post('/v1/messaging/providers/apns') ->param('endpoint', '', new Text(0), 'APNS endpoint.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = $dbForProject->createDocument('providers', new Document([ + $provider = new Document([ '$id' => $providerId, 'name' => $name, 'provider' => 'apns', 'type' => 'push', + 'default' => $default, 'credentials' => [ 'authKey' => $authKey, 'authKeyId' => $authKeyId, @@ -835,7 +982,23 @@ App::post('/v1/messaging/providers/apns') 'bundleId' => $bundleId, 'endpoint' => $endpoint, ], - ])); + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 5ab806b254..6f7725ec09 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -215,6 +215,7 @@ class Exception extends \Exception /** Provider */ public const PROVIDER_NOT_FOUND = 'provider_not_found'; + public const PROVIDER_ALREADY_EXISTS = 'provider_already_exists'; public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; protected $type = ''; From 78a53aee37a9aa754ffc366c7f054f321f306edc Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 5 Sep 2023 22:40:48 +0530 Subject: [PATCH 37/72] adds messaging event and updates messaging worker --- app/controllers/api/account.php | 61 +++++-- app/controllers/api/messaging.php | 97 ++++++++++ app/controllers/api/teams.php | 29 ++- app/init.php | 4 +- app/workers/messaging.php | 83 ++++----- composer.lock | 171 ++++++------------ docker-compose.yml | 7 +- src/Appwrite/Event/Messaging.php | 56 ++++++ src/Appwrite/Event/Phone.php | 80 -------- .../Account/AccountCustomClientTest.php | 22 ++- 10 files changed, 337 insertions(+), 273 deletions(-) create mode 100644 src/Appwrite/Event/Messaging.php delete mode 100644 src/Appwrite/Event/Phone.php diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index efc81cb370..1d73fac7c5 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -8,7 +8,6 @@ use Appwrite\Auth\Validator\Phone; use Appwrite\Detector\Detector; use Appwrite\Event\Event; use Appwrite\Event\Mail; -use Appwrite\Event\Phone as EventPhone; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Utopia\Validator\Host; @@ -45,6 +44,7 @@ use Utopia\Validator\WhiteList; use Appwrite\Auth\Validator\PasswordHistory; use Appwrite\Auth\Validator\PasswordDictionary; use Appwrite\Auth\Validator\PersonalData; +use Appwrite\Event\Messaging; $oauthDefaultSuccess = '/auth/oauth2/success'; $oauthDefaultFailure = '/auth/oauth2/failure'; @@ -1227,6 +1227,7 @@ App::post('/v1/account/sessions/phone') ->label('abuse-key', 'url:{url},email:{param-phone}') ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.') + ->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true) ->inject('request') ->inject('response') ->inject('user') @@ -1235,9 +1236,12 @@ App::post('/v1/account/sessions/phone') ->inject('events') ->inject('messaging') ->inject('locale') - ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, EventPhone $messaging, Locale $locale) { - - if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { + ->action(function (string $userId, string $phone, string $from, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, Messaging $messaging, Locale $locale) { + $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ + Query::equal('default', [true, false]), + Query::equal('type', ['sms']) + ])); + if ($provider === false || $provider->isEmpty()) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -1322,11 +1326,22 @@ App::post('/v1/account/sessions/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); - $messaging - ->setRecipient($phone) - ->setMessage($message) - ->trigger(); + $messageDoc = $dbForProject->createDocument('messages', new Document([ + 'to' => [$phone], + 'data' => [ + 'content' => $message, + 'from' => $from, + ], + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'deliveryTime' => Datetime::now(), + ])); + $messaging + ->setMessage($messageDoc) + ->setProject($project) + ->trigger(); + $events->setPayload( $response->output( $token->setAttribute('secret', $secret), @@ -2872,6 +2887,7 @@ App::post('/v1/account/verification/phone') ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) ->label('abuse-key', 'userId:{userId}') + ->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true) ->inject('request') ->inject('response') ->inject('user') @@ -2880,10 +2896,13 @@ App::post('/v1/account/verification/phone') ->inject('messaging') ->inject('project') ->inject('locale') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $events, EventPhone $messaging, Document $project, Locale $locale) { - - if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { - throw new Exception(Exception::GENERAL_PHONE_DISABLED); + ->action(function (string $from, Request $request, Response $response, Document $user, Database $dbForProject, Event $events, Messaging $messaging, Document $project, Locale $locale) { + $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ + Query::equal('default', [true, false]), + Query::equal('type', ['sms']) + ])); + if ($provider === false || $provider->isEmpty()) { + throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } if (empty($user->getAttribute('phone'))) { @@ -2928,11 +2947,21 @@ App::post('/v1/account/verification/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); + $messageDoc = $dbForProject->createDocument('messages', new Document([ + 'to' => [$user->getAttribute('phone')], + 'data' => [ + 'content' => $message, + 'from' => $from, + ], + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'deliveryTime' => Datetime::now(), + ])); + $messaging - ->setRecipient($user->getAttribute('phone')) - ->setMessage($message) - ->trigger() - ; + ->setMessage($messageDoc) + ->setProject($project) + ->trigger(); $events ->setParam('userId', $user->getId()) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e91eb48fb7..e4302883c1 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -16,7 +16,9 @@ use Utopia\Database\Validator\Datetime; use Utopia\Database\Validator\UID; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; +use Utopia\Validator\JSON; use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; App::get('/v1/messaging/providers') ->desc('List Providers') @@ -1065,6 +1067,101 @@ App::patch('/v1/messaging/providers/:id/apns') ->dynamic($provider, Response::MODEL_PROVIDER); }); +/** + * General Purpose Provider + */ +App::post('/v1/messaging/providers/general') + ->desc('Create General Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createGeneralProvider') + ->label('sdk.description', '/docs/references/messaging/create-general-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('provider', '', new Text(128), 'Provider Internal Name') + ->param('name', '', new Text(128), 'Provider name.') + ->param('type', '', new WhiteList(['push', 'email', 'sms']), 'Provider type.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('credentials', '', new JSON(), 'Provider credentials object.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $provider, string $name, string $type, bool $default, array $credentials, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => $provider, + 'type' => $type, + 'default' => $default, + 'credentials' => $credentials, + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::patch('/v1/messaging/providers/:id/general') + ->desc('Update General Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.update') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateProviderGeneral') + ->label('sdk.description', '/docs/references/messaging/update-provider-general.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('id', '', new UID(), 'Provider ID.') + ->param('name', '', new Text(128), 'Provider name.', true) + ->param('credentials', '', new JSON(), 'Provider credentials.', true) + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, string $name, array $credentials, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $id); + + if ($provider->isEmpty()) { + throw new Exception(Exception::PROVIDER_NOT_FOUND); + } + + if ($name) { + $provider->setAttribute('name', $name); + } + + if (!empty($credentials)) { + $provider->setAttribute('credentials', $credentials); + } + + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + $dbForProject->deleteCachedDocument('providers', $provider->getId()); + + $response + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + App::delete('/v1/messaging/providers/:id') ->desc('Delete Provider') ->groups(['api', 'messaging']) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index c5dd3eed12..c453eaaea1 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -6,7 +6,7 @@ use Appwrite\Detector\Detector; use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Mail; -use Appwrite\Event\Phone as EventPhone; +use Appwrite\Event\Messaging; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Utopia\Validator\Host; @@ -380,6 +380,7 @@ App::post('/v1/teams/:teamId/memberships') ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation 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, ['clients']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) + ->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true) ->inject('response') ->inject('project') ->inject('user') @@ -388,7 +389,7 @@ App::post('/v1/teams/:teamId/memberships') ->inject('mails') ->inject('messaging') ->inject('events') - ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, EventPhone $messaging, Event $events) { + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, string $from, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, Messaging $messaging, Event $events) { if (empty($userId) && empty($email) && empty($phone)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'At least one of userId, email, or phone is required'); @@ -625,6 +626,15 @@ App::post('/v1/teams/:teamId/memberships') ->trigger() ; } elseif (!empty($phone)) { + $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ + Query::equal('default', [true, false]), + Query::equal('type', ['sms']) + ])); + + if ($provider === false || $provider->isEmpty()) { + throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); + } + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; @@ -635,9 +645,20 @@ App::post('/v1/teams/:teamId/memberships') $message = $message->setParam('{{token}}', $url); $message = $message->render(); + $messageDoc = $dbForProject->createDocument('messages', new Document([ + 'to' => [$phone], + 'data' => [ + 'content' => $message, + 'from' => $from, + ], + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'deliveryTime' => Datetime::now(), + ])); + $messaging - ->setRecipient($phone) - ->setMessage($message) + ->setMessage($messageDoc) + ->setProject($project) ->trigger(); } } diff --git a/app/init.php b/app/init.php index 55757e3d28..6d90ea6dd9 100644 --- a/app/init.php +++ b/app/init.php @@ -25,7 +25,7 @@ use Appwrite\Event\Audit; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Event\Mail; -use Appwrite\Event\Phone; +use Appwrite\Event\Messaging; use Appwrite\Event\Delete; use Appwrite\GraphQL\Schema; use Appwrite\Network\Validator\Email; @@ -948,7 +948,7 @@ App::setResource('audits', fn() => new Audit()); App::setResource('mails', fn() => new Mail()); App::setResource('deletes', fn() => new Delete()); App::setResource('database', fn() => new EventDatabase()); -App::setResource('messaging', fn() => new Phone()); +App::setResource('messaging', fn() => new Messaging()); App::setResource('queue', function (Group $pools) { return $pools->get('queue')->pop()->getResource(); }, ['pools']); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 84af6fa802..ad0e5bcc4b 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -2,7 +2,9 @@ use Appwrite\Resque\Worker; use Utopia\CLI\Console; +use Utopia\Database\Document; use Utopia\Messaging\Adapters\SMS as SMSAdapter; +use Utopia\Messaging\Adapters\SMS\Mock; use Utopia\Messaging\Adapters\SMS\Msg91; use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; @@ -14,6 +16,9 @@ use Utopia\Messaging\Adapters\Push\FCM; use Utopia\Messaging\Adapters\Email as EmailAdapter; use Utopia\Messaging\Adapters\Email\Mailgun; use Utopia\Messaging\Adapters\Email\SendGrid; +use Utopia\Messaging\Messages\Email; +use Utopia\Messaging\Messages\Push; +use Utopia\Messaging\Messages\SMS; require_once __DIR__ . '/../init.php'; @@ -38,6 +43,7 @@ class MessagingV1 extends Worker { $credentials = $record->getAttribute('credentials'); return match ($record->getAttribute('provider')) { + 'mock' => new Mock('username', 'password'), 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), 'telesign' => new Telesign($credentials['username'], $credentials['password']), @@ -79,11 +85,13 @@ class MessagingV1 extends Worker public function run(): void { - $providerId = $this->args['providerId']; - $providerRecord = - $this - ->getConsoleDB() - ->getDocument('providers', $providerId); + $project = new Document($this->args['project']); + + $dbForProject = $this->getProjectDB($project); + $message = new Document($this->args['message']); + + $providerId = $message->getAttribute('providerId'); + $providerRecord =$dbForProject->getDocument('providers', $providerId); $provider = match ($providerRecord->getAttribute('type')) {//stubbbbbbed. 'sms' => $this->sms($providerRecord), @@ -96,19 +104,13 @@ class MessagingV1 extends Worker // switch on provider name // call function passing needed credentials returns required provider. - $messageId = $this->args['messageId']; - $messageRecord = - $this - ->getConsoleDB() - ->getDocument('messages', $messageId); - $message = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->buildSMSMessage($messageRecord->getArrayCopy()), - 'push' => $this->buildPushMessage($messageRecord->getArrayCopy()), - 'email' => $this->buildEmailMessage($messageRecord->getArrayCopy()), + 'sms' => $this->buildSMSMessage($message->getArrayCopy()), + 'push' => $this->buildPushMessage($message->getArrayCopy()), + 'email' => $this->buildEmailMessage($message->getArrayCopy()), default => null }; - + $provider->send($message); } @@ -117,46 +119,37 @@ class MessagingV1 extends Worker { } - private function buildEmailMessage($data): array + private function buildEmailMessage($data): Email { - $from = $data['from']; + $from = $data['data']['from']; $to = $data['to']; - $subject = $data['subject']; - $body = $data['content']; - - return [ - 'from' => $from, - 'to' => $to, - 'subject' => $subject, - 'body' => $body, - ]; + $subject = $data['data']['subject']; + $content = $data['data']['content']; + $html = $data['data']['html']; + return new Email(to: $to, subject: $subject, content: $content, from: $from, html: $html); } - private function buildSMSMessage($data): array + private function buildSMSMessage($data): SMS { - $from = $data['from']; $to = $data['to']; - $body = $data['content']; + $content = $data['data']['content']; + $from = $data['data']['from']; - return [ - 'from' => $from, - 'to' => $to, - 'body' => $body - ]; + return new SMS($to, $content, $from); } - private function buildPushMessage($data): array + private function buildPushMessage($data): Push { $to = $data['to']; - $title = $data['title']; - $body = $data['body']; - $data = $data['data']; - - return [ - 'to' => $to, - 'title' => $title, - 'body' => $body, - 'data' => $data - ]; + $title = $data['data']['title']; + $body = $data['data']['body']; + $data = $data['data']['data']; + $action = $data['data']['action']; + $sound = $data['data']['sound']; + $icon = $data['data']['icon']; + $color = $data['data']['color']; + $tag = $data['data']['tag']; + $badge = $data['data']['badge']; + return new Push($to, $title, $body, $data, $action, $sound, $icon, $color, $tag, $badge); } } diff --git a/composer.lock b/composer.lock index aeff7ad9d6..8eb26d06d7 100644 --- a/composer.lock +++ b/composer.lock @@ -386,79 +386,6 @@ }, "time": "2023-04-18T15:34:23+00:00" }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, { "name": "dragonmantank/cron-expression", "version": "v3.3.2", @@ -914,24 +841,28 @@ }, { "name": "jean85/pretty-package-versions", - "version": "1.6.0", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "1e0104b46f045868f11942aea058cd7186d6c303" + "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/1e0104b46f045868f11942aea058cd7186d6c303", - "reference": "1e0104b46f045868f11942aea058cd7186d6c303", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af", "shasum": "" }, "require": { - "composer/package-versions-deprecated": "^1.8.0", - "php": "^7.0|^8.0" + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.0|^8.5|^9.2" + "friendsofphp/php-cs-fixer": "^2.17", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^0.12.66", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" }, "type": "library", "extra": { @@ -954,7 +885,7 @@ "email": "alessandro.lai85@gmail.com" } ], - "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "description": "A library to get pretty versions strings of installed dependencies", "keywords": [ "composer", "package", @@ -963,9 +894,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/1.6.0" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" }, - "time": "2021-02-04T16:20:16+00:00" + "time": "2021-10-08T21:21:46+00:00" }, { "name": "laravel/pint", @@ -1188,34 +1119,35 @@ }, { "name": "mongodb/mongodb", - "version": "1.8.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/mongodb/mongo-php-library.git", - "reference": "953dbc19443aa9314c44b7217a16873347e6840d" + "reference": "b0bbd657f84219212487d01a8ffe93a789e1e488" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/953dbc19443aa9314c44b7217a16873347e6840d", - "reference": "953dbc19443aa9314c44b7217a16873347e6840d", + "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/b0bbd657f84219212487d01a8ffe93a789e1e488", + "reference": "b0bbd657f84219212487d01a8ffe93a789e1e488", "shasum": "" }, "require": { "ext-hash": "*", "ext-json": "*", - "ext-mongodb": "^1.8.1", - "jean85/pretty-package-versions": "^1.2", - "php": "^7.0 || ^8.0", + "ext-mongodb": "^1.11.0", + "jean85/pretty-package-versions": "^1.2 || ^2.0.1", + "php": "^7.1 || ^8.0", "symfony/polyfill-php80": "^1.19" }, "require-dev": { - "squizlabs/php_codesniffer": "^3.5, <3.5.5", - "symfony/phpunit-bridge": "5.x-dev" + "doctrine/coding-standard": "^9.0", + "squizlabs/php_codesniffer": "^3.6", + "symfony/phpunit-bridge": "^5.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { @@ -1250,9 +1182,9 @@ ], "support": { "issues": "https://github.com/mongodb/mongo-php-library/issues", - "source": "https://github.com/mongodb/mongo-php-library/tree/1.8.0" + "source": "https://github.com/mongodb/mongo-php-library/tree/1.10.0" }, - "time": "2020-11-25T12:26:02+00:00" + "time": "2021-10-20T22:22:37+00:00" }, { "name": "mustangostang/spyc", @@ -2220,16 +2152,16 @@ }, { "name": "utopia-php/database", - "version": "0.43.0", + "version": "0.43.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "fb96fc6c94d5efcd43913c34bece62daba76a5e9" + "reference": "cc0247f4f0c402b39f663bf9f77b29d69b95f9d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/fb96fc6c94d5efcd43913c34bece62daba76a5e9", - "reference": "fb96fc6c94d5efcd43913c34bece62daba76a5e9", + "url": "https://api.github.com/repos/utopia-php/database/zipball/cc0247f4f0c402b39f663bf9f77b29d69b95f9d6", + "reference": "cc0247f4f0c402b39f663bf9f77b29d69b95f9d6", "shasum": "" }, "require": { @@ -2238,12 +2170,11 @@ "php": ">=8.0", "utopia-php/cache": "0.8.*", "utopia-php/framework": "0.*.*", - "utopia-php/mongo": "0.2.*" + "utopia-php/mongo": "0.3.*" }, "require-dev": { "fakerphp/faker": "^1.14", "laravel/pint": "1.4.*", - "mongodb/mongodb": "1.8.0", "pcov/clobber": "^2.0", "phpstan/phpstan": "1.10.*", "phpunit/phpunit": "^9.4", @@ -2271,9 +2202,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.43.0" + "source": "https://github.com/utopia-php/database/tree/0.43.1" }, - "time": "2023-08-29T10:18:39+00:00" + "time": "2023-09-01T20:38:36+00:00" }, { "name": "utopia-php/domains", @@ -2589,12 +2520,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "36aee6ae3c601b796364e35be083b909e02bef66" + "reference": "4ebebe97d80bb1de10d362c2464ba28717d333ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/36aee6ae3c601b796364e35be083b909e02bef66", - "reference": "36aee6ae3c601b796364e35be083b909e02bef66", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/4ebebe97d80bb1de10d362c2464ba28717d333ac", + "reference": "4ebebe97d80bb1de10d362c2464ba28717d333ac", "shasum": "" }, "require": { @@ -2629,7 +2560,7 @@ "issues": "https://github.com/utopia-php/messaging/issues", "source": "https://github.com/utopia-php/messaging/tree/feat-push" }, - "time": "2023-08-30T18:32:54+00:00" + "time": "2023-09-01T14:13:03+00:00" }, { "name": "utopia-php/migration", @@ -2691,21 +2622,21 @@ }, { "name": "utopia-php/mongo", - "version": "0.2.0", + "version": "0.3.1", "source": { "type": "git", "url": "https://github.com/utopia-php/mongo.git", - "reference": "b6dfb31b93c07c59b8bbd62a3b52e3b97a407c09" + "reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/mongo/zipball/b6dfb31b93c07c59b8bbd62a3b52e3b97a407c09", - "reference": "b6dfb31b93c07c59b8bbd62a3b52e3b97a407c09", + "url": "https://api.github.com/repos/utopia-php/mongo/zipball/52326a9a43e2d27ff0c15c48ba746dacbe9a7aee", + "reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee", "shasum": "" }, "require": { "ext-mongodb": "*", - "mongodb/mongodb": "1.8.0", + "mongodb/mongodb": "1.10.0", "php": ">=8.0" }, "require-dev": { @@ -2745,9 +2676,9 @@ ], "support": { "issues": "https://github.com/utopia-php/mongo/issues", - "source": "https://github.com/utopia-php/mongo/tree/0.2.0" + "source": "https://github.com/utopia-php/mongo/tree/0.3.1" }, - "time": "2023-03-22T10:44:29+00:00" + "time": "2023-09-01T17:25:28+00:00" }, { "name": "utopia-php/orchestration", @@ -3460,16 +3391,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.34.1", + "version": "0.34.2", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "81538d10abacd81350c265b516c72ef315116013" + "reference": "06ea25aace27790e42d57fdbc7ccf97e0b31a6ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/81538d10abacd81350c265b516c72ef315116013", - "reference": "81538d10abacd81350c265b516c72ef315116013", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/06ea25aace27790e42d57fdbc7ccf97e0b31a6ba", + "reference": "06ea25aace27790e42d57fdbc7ccf97e0b31a6ba", "shasum": "" }, "require": { @@ -3505,9 +3436,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.34.1" + "source": "https://github.com/appwrite/sdk-generator/tree/0.34.2" }, - "time": "2023-08-30T07:57:31+00:00" + "time": "2023-08-31T14:10:33+00:00" }, { "name": "doctrine/deprecations", diff --git a/docker-compose.yml b/docker-compose.yml index b27c3581af..fe1237c95f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -544,8 +544,11 @@ services: - _APP_REDIS_PORT - _APP_REDIS_USER - _APP_REDIS_PASS - - _APP_SMS_PROVIDER - - _APP_SMS_FROM + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS - _APP_LOGGING_PROVIDER - _APP_LOGGING_CONFIG diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php new file mode 100644 index 0000000000..db60d2ee23 --- /dev/null +++ b/src/Appwrite/Event/Messaging.php @@ -0,0 +1,56 @@ +message = $message; + + return $this; + } + + /** + * Returns set message for the messaging event. + * + * @return Document + */ + public function getMessage(): Document + { + return $this->message; + } + + /** + * Executes the event and sends it to the messaging worker. + * + * @return string|bool + * @throws \InvalidArgumentException + */ + public function trigger(): string|bool + { + return Resque::enqueue($this->queue, $this->class, [ + 'project' => $this->project, + 'user' => $this->user, + 'message' => $this->message, + ]); + } +} diff --git a/src/Appwrite/Event/Phone.php b/src/Appwrite/Event/Phone.php deleted file mode 100644 index 8baa5120c9..0000000000 --- a/src/Appwrite/Event/Phone.php +++ /dev/null @@ -1,80 +0,0 @@ -recipient = $recipient; - - return $this; - } - - /** - * Returns set recipient for this messaging event. - * - * @return string - */ - public function getRecipient(): string - { - return $this->recipient; - } - - /** - * Sets url for the messaging event. - * - * @param string $message - * @return self - */ - public function setMessage(string $message): self - { - $this->message = $message; - - return $this; - } - - /** - * Returns set url for the messaging event. - * - * @return string - */ - public function getMessage(): string - { - return $this->message; - } - - /** - * Executes the event and sends it to the messaging worker. - * - * @return string|bool - * @throws \InvalidArgumentException - */ - public function trigger(): string|bool - { - return Resque::enqueue($this->queue, $this->class, [ - 'project' => $this->project, - 'user' => $this->user, - 'payload' => $this->payload, - 'recipient' => $this->recipient, - 'message' => $this->message, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); - } -} diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 1441ab7f98..55ad0ddae3 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -2,8 +2,6 @@ namespace Tests\E2E\Services\Account; -use Appwrite\Extend\Exception; -use Appwrite\SMS\Adapter\Mock; use Appwrite\Tests\Retry; use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; @@ -745,7 +743,22 @@ class AccountCustomClientTest extends Scope public function testCreatePhone(): array { $number = '+123456789'; - + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/general' , \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'providerId' => 'unique()', + 'name' => 'Mock', + 'provider' => 'mock', + 'type' => 'sms', + 'credentials' => [ + 'username' => 'username', + 'password' => 'password', + ], + 'default' => true, + ]); + $this->assertEquals(201, $response['headers']['status-code']); /** * Test for SUCCESS */ @@ -756,6 +769,7 @@ class AccountCustomClientTest extends Scope ]), [ 'userId' => ID::unique(), 'phone' => $number, + 'from' => $number, ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -999,7 +1013,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ])); + ]), ['from' => 'Appwrite']); $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); From 38d81c058b134466f8d5d85e2642b33f0470ace7 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 5 Sep 2023 23:10:33 +0530 Subject: [PATCH 38/72] lint fix --- app/controllers/api/account.php | 6 +++--- app/controllers/api/teams.php | 2 +- app/workers/messaging.php | 4 ++-- src/Appwrite/Event/Messaging.php | 2 +- tests/e2e/Services/Account/AccountCustomClientTest.php | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 1d73fac7c5..4b91af093f 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1238,7 +1238,7 @@ App::post('/v1/account/sessions/phone') ->inject('locale') ->action(function (string $userId, string $phone, string $from, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, Messaging $messaging, Locale $locale) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true, false]), + Query::equal('default', [true, false]), Query::equal('type', ['sms']) ])); if ($provider === false || $provider->isEmpty()) { @@ -1341,7 +1341,7 @@ App::post('/v1/account/sessions/phone') ->setMessage($messageDoc) ->setProject($project) ->trigger(); - + $events->setPayload( $response->output( $token->setAttribute('secret', $secret), @@ -2898,7 +2898,7 @@ App::post('/v1/account/verification/phone') ->inject('locale') ->action(function (string $from, Request $request, Response $response, Document $user, Database $dbForProject, Event $events, Messaging $messaging, Document $project, Locale $locale) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true, false]), + Query::equal('default', [true, false]), Query::equal('type', ['sms']) ])); if ($provider === false || $provider->isEmpty()) { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index c453eaaea1..9588cb9c12 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -627,7 +627,7 @@ App::post('/v1/teams/:teamId/memberships') ; } elseif (!empty($phone)) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true, false]), + Query::equal('default', [true, false]), Query::equal('type', ['sms']) ])); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index ad0e5bcc4b..079ff3397b 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -91,7 +91,7 @@ class MessagingV1 extends Worker $message = new Document($this->args['message']); $providerId = $message->getAttribute('providerId'); - $providerRecord =$dbForProject->getDocument('providers', $providerId); + $providerRecord = $dbForProject->getDocument('providers', $providerId); $provider = match ($providerRecord->getAttribute('type')) {//stubbbbbbed. 'sms' => $this->sms($providerRecord), @@ -110,7 +110,7 @@ class MessagingV1 extends Worker 'email' => $this->buildEmailMessage($message->getArrayCopy()), default => null }; - + $provider->send($message); } diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index db60d2ee23..9616f93a21 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -13,7 +13,7 @@ class Messaging extends Event { parent::__construct(Event::MESSAGING_QUEUE_NAME, Event::MESSAGING_CLASS_NAME); } - + /** diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 55ad0ddae3..9f922d63e2 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -743,7 +743,7 @@ class AccountCustomClientTest extends Scope public function testCreatePhone(): array { $number = '+123456789'; - $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/general' , \array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/general', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], From 039e717d721d9c740f95ab32f682511bb5527604 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 6 Sep 2023 15:40:56 +0530 Subject: [PATCH 39/72] fixes in send email endpoint --- app/controllers/api/messaging.php | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e4302883c1..d5ff8784e6 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1,7 +1,9 @@ label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('providerId', '', new Text(128), 'Email Provider ID.') - ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.', true) - ->param('subject', null, new Text(0), 'Email Subject.', true) - ->param('content', null, new Text(0), 'Email Content.', true) - ->param('from', null, new Text(0), 'Email from.', false) - ->param('html', null, new Text(0), 'Is content of type HTML', false) - ->param('deliveryTime', null, new Datetime(), 'Delivery time of the message', false) + ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.') + ->param('subject', '', new Text(0), 'Email Subject.') + ->param('content', '', new Text(0), 'Email Content.') + ->param('from', '', new Text(0), 'Email from.') + ->param('html', false, new Boolean(false), 'Is content of type HTML', true) + ->param('deliveryTime', '', new DatetimeValidator(), 'Delivery time of the message', true) ->inject('dbForProject') - ->inject('events') + ->inject('project') + ->inject('messaging') ->inject('response') - ->action(function (string $providerId, string $to, string $subject, string $content, string $from, string $html, DateTime $deliveryTime, Database $dbForProject, Event $eventsInstance, Response $response) { + ->action(function (string $providerId, array $to, string $subject, string $content, string $from, string $html, string $deliveryTime, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1228,6 +1231,8 @@ App::post('/v1/messaging/messages/email') 'data' => [ 'subject' => $subject, 'content' => $content, + 'from' => $from, + 'html' => $html ], 'deliveryTime' => $deliveryTime, 'deliveryError' => null, @@ -1236,7 +1241,10 @@ App::post('/v1/messaging/messages/email') 'search' => null, ])); - $eventsInstance->setParam('messageId', $message->getId()); + $messaging + ->setMessage($message) + ->setProject($project) + ->trigger(); $response ->setStatusCode(Response::STATUS_CODE_CREATED) From 15773a35617057700c064a1a71ffe2c86bfc6a1c Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 6 Sep 2023 16:30:46 +0530 Subject: [PATCH 40/72] sets the correct response for send email --- app/controllers/api/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index d5ff8784e6..f71219f010 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1248,5 +1248,5 @@ App::post('/v1/messaging/messages/email') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_MESSAGE); + ->dynamic($message, Response::MODEL_MESSAGE); }); From 2ecf9ee98a7801390f0873a1b549f46224dbf3aa Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Mon, 11 Sep 2023 19:53:48 +0530 Subject: [PATCH 41/72] udpates send email endpoint according to collection changes --- app/controllers/api/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index f71219f010..5355b56721 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1235,7 +1235,7 @@ App::post('/v1/messaging/messages/email') 'html' => $html ], 'deliveryTime' => $deliveryTime, - 'deliveryError' => null, + 'deliveryErrors' => null, 'deliveredTo' => null, 'delivered' => false, 'search' => null, From d742b0c0a9dc2522c0b6d73a35b49b699d1d3901 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 13 Sep 2023 00:53:25 +0530 Subject: [PATCH 42/72] removes provider type from create user target --- app/controllers/api/users.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 2618941ba2..78a0e086d4 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -430,7 +430,6 @@ App::post('/v1/users/:userId/targets') ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), - 'providerType' => null, 'userId' => $userId, 'userInternalId' => $user->getInternalId(), 'identifier' => $identifier, From 0066216bef1757562282fe6852094e80e3ad3c7c Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 13 Sep 2023 17:47:38 +0530 Subject: [PATCH 43/72] adds enabled param for provider endpoints and review changes --- app/controllers/api/messaging.php | 124 +++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 27 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 5355b56721..dbf149fd31 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -107,11 +107,12 @@ App::post('/v1/messaging/providers/mailgun') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, string $domain, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ @@ -120,6 +121,7 @@ App::post('/v1/messaging/providers/mailgun') 'provider' => 'mailgun', 'type' => 'email', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'apiKey' => $apiKey, 'domain' => $domain, @@ -161,11 +163,12 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) ->param('domain', '', new Text(0), 'Mailgun Domain.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $apiKey, string $domain, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -181,8 +184,12 @@ App::patch('/v1/messaging/providers/:id/mailgun') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($apiKey || $domain) { - // Check if all five variables are present + // Check if all credential variables are present if ($apiKey && $domain) { $provider->setAttribute('credentials', [ 'apiKey' => $apiKey, @@ -217,10 +224,11 @@ App::post('/v1/messaging/providers/sendgrid') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Sendgrid API key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -228,6 +236,7 @@ App::post('/v1/messaging/providers/sendgrid') 'provider' => 'sendgrid', 'type' => 'email', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'apiKey' => $apiKey, ], @@ -268,10 +277,11 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $apiKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -287,6 +297,10 @@ App::patch('/v1/messaging/providers/:id/sendgrid') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($apiKey) { $provider->setAttribute('credentials', [ 'apiKey' => $apiKey, @@ -319,11 +333,12 @@ App::post('/v1/messaging/providers/msg91') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $senderId, string $authKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -331,6 +346,7 @@ App::post('/v1/messaging/providers/msg91') 'provider' => 'msg91', 'type' => 'sms', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'senderId' => $senderId, 'authKey' => $authKey, @@ -372,11 +388,12 @@ App::patch('/v1/messaging/providers/:id/msg91') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $senderId, string $authKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -392,8 +409,12 @@ App::patch('/v1/messaging/providers/:id/msg91') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($senderId || $authKey) { - // Check if all five variables are present + // Check if all credential variables are present if ($senderId && $authKey) { $provider->setAttribute('credentials', [ 'senderId' => $senderId, @@ -428,11 +449,12 @@ App::post('/v1/messaging/providers/telesign') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Telesign username.') ->param('password', '', new Text(0), 'Telesign password.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $username, string $password, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -440,6 +462,7 @@ App::post('/v1/messaging/providers/telesign') 'provider' => 'telesign', 'type' => 'sms', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'username' => $username, 'password' => $password, @@ -481,11 +504,12 @@ App::patch('/v1/messaging/providers/:id/telesign') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Telesign username.', true) ->param('password', '', new Text(0), 'Telesign password.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $username, string $password, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -501,8 +525,12 @@ App::patch('/v1/messaging/providers/:id/telesign') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($username || $password) { - // Check if all five variables are present + // Check if all credential variables are present if ($username && $password) { $provider->setAttribute('credentials', [ 'username' => $username, @@ -537,11 +565,12 @@ App::post('/v1/messaging/providers/textmagic') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Textmagic username.') ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $username, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -549,6 +578,7 @@ App::post('/v1/messaging/providers/textmagic') 'provider' => 'text-magic', 'type' => 'sms', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'username' => $username, 'apiKey' => $apiKey, @@ -590,11 +620,12 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Textmagic username.', true) ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $username, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -610,8 +641,12 @@ App::patch('/v1/messaging/providers/:id/textmagic') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($username || $apiKey) { - // Check if all five variables are present + // Check if all credential variables are present if ($username && $apiKey) { $provider->setAttribute('credentials', [ 'username' => $username, @@ -646,11 +681,12 @@ App::post('/v1/messaging/providers/twilio') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') ->param('authToken', '', new Text(0), 'Twilio authentication token.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -658,6 +694,7 @@ App::post('/v1/messaging/providers/twilio') 'provider' => 'twilio', 'type' => 'sms', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'accountSid' => $accountSid, 'authToken' => $authToken, @@ -699,11 +736,12 @@ App::patch('/v1/messaging/providers/:id/twilio') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -719,8 +757,12 @@ App::patch('/v1/messaging/providers/:id/twilio') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($accountSid || $authToken) { - // Check if all five variables are present + // Check if all credential variables are present if ($accountSid && $authToken) { $provider->setAttribute('credentials', [ 'accountSid' => $accountSid, @@ -755,11 +797,12 @@ App::post('/v1/messaging/providers/vonage') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Vonage API key.') ->param('apiSecret', '', new Text(0), 'Vonage API secret.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -767,6 +810,7 @@ App::post('/v1/messaging/providers/vonage') 'provider' => 'vonage', 'type' => 'sms', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'apiKey' => $apiKey, 'apiSecret' => $apiSecret, @@ -808,11 +852,12 @@ App::patch('/v1/messaging/providers/:id/vonage') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Vonage API key.', true) ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -828,8 +873,12 @@ App::patch('/v1/messaging/providers/:id/vonage') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($apiKey || $apiSecret) { - // Check if all five variables are present + // Check if all credential variables are present if ($apiKey && $apiSecret) { $provider->setAttribute('credentials', [ 'apiKey' => $apiKey, @@ -867,10 +916,11 @@ App::post('/v1/messaging/providers/fcm') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('serverKey', '', new Text(0), 'FCM Server Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $serverKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $serverKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -878,6 +928,7 @@ App::post('/v1/messaging/providers/fcm') 'provider' => 'fcm', 'type' => 'push', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'serverKey' => $serverKey, ], @@ -918,10 +969,11 @@ App::patch('/v1/messaging/providers/:id/fcm') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $serverKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $serverKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -937,6 +989,10 @@ App::patch('/v1/messaging/providers/:id/fcm') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($serverKey) { $provider->setAttribute('credentials', ['serverKey' => $serverKey]); } @@ -964,6 +1020,7 @@ App::post('/v1/messaging/providers/apns') ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('authKey', '', new Text(0), 'APNS authentication key.') ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') ->param('teamId', '', new Text(0), 'APNS team ID.') @@ -971,7 +1028,7 @@ App::post('/v1/messaging/providers/apns') ->param('endpoint', '', new Text(0), 'APNS endpoint.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -979,6 +1036,7 @@ App::post('/v1/messaging/providers/apns') 'provider' => 'apns', 'type' => 'push', 'default' => $default, + 'enabled' => $enabled, 'credentials' => [ 'authKey' => $authKey, 'authKeyId' => $authKeyId, @@ -1023,6 +1081,7 @@ App::patch('/v1/messaging/providers/:id/apns') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('authKey', '', new Text(0), 'APNS authentication key.', true) ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) ->param('teamId', '', new Text(0), 'APNS team ID.', true) @@ -1030,7 +1089,7 @@ App::patch('/v1/messaging/providers/:id/apns') ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -1046,8 +1105,12 @@ App::patch('/v1/messaging/providers/:id/apns') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { - // Check if all five variables are present + // Check if all credential variables are present if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { $provider->setAttribute('credentials', [ 'authKey' => $authKey, @@ -1090,10 +1153,11 @@ App::post('/v1/messaging/providers/general') ->param('name', '', new Text(128), 'Provider name.') ->param('type', '', new WhiteList(['push', 'email', 'sms']), 'Provider type.') ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('credentials', '', new JSON(), 'Provider credentials object.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $provider, string $name, string $type, bool $default, array $credentials, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $provider, string $name, string $type, bool $default, bool $enabled, array $credentials, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -1101,6 +1165,7 @@ App::post('/v1/messaging/providers/general') 'provider' => $provider, 'type' => $type, 'default' => $default, + 'enabled' => $enabled, 'credentials' => $credentials, ]); @@ -1139,10 +1204,11 @@ App::patch('/v1/messaging/providers/:id/general') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) ->param('credentials', '', new JSON(), 'Provider credentials.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, array $credentials, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, array $credentials, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -1153,6 +1219,10 @@ App::patch('/v1/messaging/providers/:id/general') $provider->setAttribute('name', $name); } + if ($enabled === false) { + $provider->setAttribute('enabled', $enabled); + } + if (!empty($credentials)) { $provider->setAttribute('credentials', $credentials); } From bd36a09473087b5a3cb715ce6c0127e508620f0f Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Tue, 19 Sep 2023 15:36:40 +0530 Subject: [PATCH 44/72] adds search in messaging controllers, updated mailgun endpoint with isEu param --- app/controllers/api/messaging.php | 63 +++++++++++++++------- composer.lock | 86 +++++++++++++++---------------- 2 files changed, 87 insertions(+), 62 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index dbf149fd31..a3a0c48b8c 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -108,11 +108,12 @@ App::post('/v1/messaging/providers/mailgun') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('isEuRegion', false, new Boolean(), 'Set as eu region.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, bool $isEuRegion, string $apiKey, string $domain, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ @@ -122,9 +123,11 @@ App::post('/v1/messaging/providers/mailgun') 'type' => 'email', 'default' => $default, 'enabled' => $enabled, + 'search' => $providerId . ' ' . $name . ' ' . 'mailgun' . ' ' . 'email', 'credentials' => [ 'apiKey' => $apiKey, 'domain' => $domain, + 'isEuRegion' => $isEuRegion, ], ]); @@ -164,11 +167,12 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('isEuRegion', false, new Boolean(), 'Set as eu region.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) ->param('domain', '', new Text(0), 'Mailgun Domain.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, bool $enabled, bool $isEuRegion, string $apiKey, string $domain, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -182,9 +186,19 @@ App::patch('/v1/messaging/providers/:id/mailgun') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'mailgun' . ' ' . 'email'); } - if ($enabled === false) { + if ($isEuRegion === true || $isEuRegion === false) { + $credentials = $provider->getAttribute('credentials'); + $provider->setAttribute('credentials', [ + 'isEuRegion' => $isEuRegion, + 'apiKey' => $credentials['apiKey'], + 'domain' => $credentials['domain'], + ]); + } + + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -237,6 +251,7 @@ App::post('/v1/messaging/providers/sendgrid') 'type' => 'email', 'default' => $default, 'enabled' => $enabled, + 'search' => $providerId . ' ' . $name . ' ' . 'sendgrid' . ' ' . 'email', 'credentials' => [ 'apiKey' => $apiKey, ], @@ -295,9 +310,10 @@ App::patch('/v1/messaging/providers/:id/sendgrid') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'sendgrid' . ' ' . 'email'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -345,6 +361,7 @@ App::post('/v1/messaging/providers/msg91') 'name' => $name, 'provider' => 'msg91', 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'msg91' . ' ' . 'sms', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -407,9 +424,10 @@ App::patch('/v1/messaging/providers/:id/msg91') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'msg91' . ' ' . 'sms'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -461,6 +479,7 @@ App::post('/v1/messaging/providers/telesign') 'name' => $name, 'provider' => 'telesign', 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'telesign' . ' ' . 'sms', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -523,9 +542,10 @@ App::patch('/v1/messaging/providers/:id/telesign') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'telesign' . ' ' . 'sms'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -577,6 +597,7 @@ App::post('/v1/messaging/providers/textmagic') 'name' => $name, 'provider' => 'text-magic', 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'text-magic' . ' ' . 'sms', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -639,9 +660,10 @@ App::patch('/v1/messaging/providers/:id/textmagic') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'textmagic' . ' ' . 'sms'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -693,6 +715,7 @@ App::post('/v1/messaging/providers/twilio') 'name' => $name, 'provider' => 'twilio', 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'twilio' . ' ' . 'sms', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -755,9 +778,10 @@ App::patch('/v1/messaging/providers/:id/twilio') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'twilio' . ' ' . 'sms'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -809,6 +833,7 @@ App::post('/v1/messaging/providers/vonage') 'name' => $name, 'provider' => 'vonage', 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'vonage' . ' ' . 'sms', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -871,9 +896,10 @@ App::patch('/v1/messaging/providers/:id/vonage') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'vonage' . ' ' . 'sms'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -927,6 +953,7 @@ App::post('/v1/messaging/providers/fcm') 'name' => $name, 'provider' => 'fcm', 'type' => 'push', + 'search' => $providerId . ' ' . $name . ' ' . 'fcm' . ' ' . 'push', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -987,9 +1014,10 @@ App::patch('/v1/messaging/providers/:id/fcm') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'fcm' . ' ' . 'push'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -1035,6 +1063,7 @@ App::post('/v1/messaging/providers/apns') 'name' => $name, 'provider' => 'apns', 'type' => 'push', + 'search' => $providerId . ' ' . $name . ' ' . 'apns' . ' ' . 'push', 'default' => $default, 'enabled' => $enabled, 'credentials' => [ @@ -1103,9 +1132,10 @@ App::patch('/v1/messaging/providers/:id/apns') if ($name) { $provider->setAttribute('name', $name); + $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'apns' . ' ' . 'push'); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -1219,7 +1249,7 @@ App::patch('/v1/messaging/providers/:id/general') $provider->setAttribute('name', $name); } - if ($enabled === false) { + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -1280,9 +1310,8 @@ App::post('/v1/messaging/messages/email') ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.') ->param('subject', '', new Text(0), 'Email Subject.') ->param('content', '', new Text(0), 'Email Content.') - ->param('from', '', new Text(0), 'Email from.') + ->param('from', '', new Text(0), 'Email from.', true) ->param('html', false, new Boolean(false), 'Is content of type HTML', true) - ->param('deliveryTime', '', new DatetimeValidator(), 'Delivery time of the message', true) ->inject('dbForProject') ->inject('project') ->inject('messaging') @@ -1304,11 +1333,7 @@ App::post('/v1/messaging/messages/email') 'from' => $from, 'html' => $html ], - 'deliveryTime' => $deliveryTime, - 'deliveryErrors' => null, - 'deliveredTo' => null, - 'delivered' => false, - 'search' => null, + 'search' => $subject . ' ' . $from, ])); $messaging diff --git a/composer.lock b/composer.lock index 8eb26d06d7..279847dedc 100644 --- a/composer.lock +++ b/composer.lock @@ -65,16 +65,16 @@ }, { "name": "appwrite/appwrite", - "version": "8.0.0", + "version": "10.0.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-for-php.git", - "reference": "2b9e966edf35c4061179ed98ea364698ab30de8b" + "reference": "461eedf4efd502dc905c3055f36f0e3583f67390" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/2b9e966edf35c4061179ed98ea364698ab30de8b", - "reference": "2b9e966edf35c4061179ed98ea364698ab30de8b", + "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/461eedf4efd502dc905c3055f36f0e3583f67390", + "reference": "461eedf4efd502dc905c3055f36f0e3583f67390", "shasum": "" }, "require": { @@ -99,10 +99,10 @@ "support": { "email": "team@appwrite.io", "issues": "https://github.com/appwrite/sdk-for-php/issues", - "source": "https://github.com/appwrite/sdk-for-php/tree/8.0.0", + "source": "https://github.com/appwrite/sdk-for-php/tree/10.0.0", "url": "https://appwrite.io/support" }, - "time": "2023-04-12T10:16:28+00:00" + "time": "2023-09-07T23:28:31+00:00" }, { "name": "appwrite/php-clamav", @@ -2152,16 +2152,16 @@ }, { "name": "utopia-php/database", - "version": "0.43.1", + "version": "0.43.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "cc0247f4f0c402b39f663bf9f77b29d69b95f9d6" + "reference": "f2626acd42665a9987c94af1c93bf20c28d55c9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/cc0247f4f0c402b39f663bf9f77b29d69b95f9d6", - "reference": "cc0247f4f0c402b39f663bf9f77b29d69b95f9d6", + "url": "https://api.github.com/repos/utopia-php/database/zipball/f2626acd42665a9987c94af1c93bf20c28d55c9d", + "reference": "f2626acd42665a9987c94af1c93bf20c28d55c9d", "shasum": "" }, "require": { @@ -2202,9 +2202,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.43.1" + "source": "https://github.com/utopia-php/database/tree/0.43.2" }, - "time": "2023-09-01T20:38:36+00:00" + "time": "2023-09-07T19:04:33+00:00" }, { "name": "utopia-php/domains", @@ -2520,12 +2520,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "4ebebe97d80bb1de10d362c2464ba28717d333ac" + "reference": "2bb09220d0993a9f8f0afc63ff51382b13d93e18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/4ebebe97d80bb1de10d362c2464ba28717d333ac", - "reference": "4ebebe97d80bb1de10d362c2464ba28717d333ac", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/2bb09220d0993a9f8f0afc63ff51382b13d93e18", + "reference": "2bb09220d0993a9f8f0afc63ff51382b13d93e18", "shasum": "" }, "require": { @@ -2534,8 +2534,8 @@ }, "require-dev": { "laravel/pint": "^1.2", - "phpmailer/phpmailer": "^6.8", - "phpunit/phpunit": "^9.6" + "phpmailer/phpmailer": "6.8.*", + "phpunit/phpunit": "9.6.*" }, "type": "library", "autoload": { @@ -2560,31 +2560,31 @@ "issues": "https://github.com/utopia-php/messaging/issues", "source": "https://github.com/utopia-php/messaging/tree/feat-push" }, - "time": "2023-09-01T14:13:03+00:00" + "time": "2023-09-14T20:29:49+00:00" }, { "name": "utopia-php/migration", - "version": "0.3.2", + "version": "0.3.4", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "49a28adfbb781f0c08f1eaf459a8fbb8ab9fcc70" + "reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/49a28adfbb781f0c08f1eaf459a8fbb8ab9fcc70", - "reference": "49a28adfbb781f0c08f1eaf459a8fbb8ab9fcc70", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/ade836d61b3e1547bc9f0dc300ee75b24ab49f7a", + "reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a", "shasum": "" }, "require": { - "appwrite/appwrite": "^8.0", - "php": ">=8.0", - "utopia-php/cli": "^0.15.0" + "appwrite/appwrite": "10.0.*", + "php": "8.*", + "utopia-php/cli": "0.*" }, "require-dev": { - "laravel/pint": "^1.10", - "phpunit/phpunit": "^9.3", - "vlucas/phpdotenv": "^5.5" + "laravel/pint": "1.*", + "phpunit/phpunit": "9.*", + "vlucas/phpdotenv": "5.*" }, "type": "library", "autoload": { @@ -2616,9 +2616,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.3.2" + "source": "https://github.com/utopia-php/migration/tree/0.3.4" }, - "time": "2023-08-31T04:11:35+00:00" + "time": "2023-09-14T17:17:55+00:00" }, { "name": "utopia-php/mongo", @@ -4145,16 +4145,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.23.1", + "version": "1.24.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "846ae76eef31c6d7790fac9bc399ecee45160b26" + "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/846ae76eef31c6d7790fac9bc399ecee45160b26", - "reference": "846ae76eef31c6d7790fac9bc399ecee45160b26", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/3510b0a6274cc42f7219367cb3abfc123ffa09d6", + "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6", "shasum": "" }, "require": { @@ -4186,22 +4186,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.0" }, - "time": "2023-08-03T16:32:59+00:00" + "time": "2023-09-07T20:46:32+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.27", + "version": "9.2.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" + "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", - "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", + "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", "shasum": "" }, "require": { @@ -4258,7 +4258,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.28" }, "funding": [ { @@ -4266,7 +4266,7 @@ "type": "github" } ], - "time": "2023-07-26T13:44:30+00:00" + "time": "2023-09-12T14:36:20+00:00" }, { "name": "phpunit/php-file-iterator", @@ -6036,5 +6036,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 67397cd763d5bab07788153418507bb0d90c5ef6 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 15:55:22 +0530 Subject: [PATCH 45/72] fix tests and code changes --- app/controllers/api/messaging.php | 60 +++++++++---------- composer.lock | 24 ++++---- .../e2e/Services/Messaging/MessagingBase.php | 15 +++++ 3 files changed, 57 insertions(+), 42 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index a3a0c48b8c..b2585418eb 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -166,13 +166,13 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('isEuRegion', false, new Boolean(), 'Set as eu region.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) ->param('domain', '', new Text(0), 'Mailgun Domain.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, bool $isEuRegion, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, bool $isEuRegion, string $apiKey, string $domain, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -184,7 +184,7 @@ App::patch('/v1/messaging/providers/:id/mailgun') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'mailgun' . ' ' . 'email'); } @@ -292,11 +292,11 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $apiKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -308,7 +308,7 @@ App::patch('/v1/messaging/providers/:id/sendgrid') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'sendgrid' . ' ' . 'email'); } @@ -405,12 +405,12 @@ App::patch('/v1/messaging/providers/:id/msg91') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -422,7 +422,7 @@ App::patch('/v1/messaging/providers/:id/msg91') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'msg91' . ' ' . 'sms'); } @@ -523,12 +523,12 @@ App::patch('/v1/messaging/providers/:id/telesign') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Telesign username.', true) ->param('password', '', new Text(0), 'Telesign password.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -540,7 +540,7 @@ App::patch('/v1/messaging/providers/:id/telesign') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'telesign' . ' ' . 'sms'); } @@ -641,12 +641,12 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Textmagic username.', true) ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -658,7 +658,7 @@ App::patch('/v1/messaging/providers/:id/textmagic') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'textmagic' . ' ' . 'sms'); } @@ -759,12 +759,12 @@ App::patch('/v1/messaging/providers/:id/twilio') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -776,7 +776,7 @@ App::patch('/v1/messaging/providers/:id/twilio') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'twilio' . ' ' . 'sms'); } @@ -877,12 +877,12 @@ App::patch('/v1/messaging/providers/:id/vonage') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Vonage API key.', true) ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -894,7 +894,7 @@ App::patch('/v1/messaging/providers/:id/vonage') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'vonage' . ' ' . 'sms'); } @@ -996,11 +996,11 @@ App::patch('/v1/messaging/providers/:id/fcm') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $serverKey, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $serverKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -1012,7 +1012,7 @@ App::patch('/v1/messaging/providers/:id/fcm') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'fcm' . ' ' . 'push'); } @@ -1110,7 +1110,7 @@ App::patch('/v1/messaging/providers/:id/apns') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('authKey', '', new Text(0), 'APNS authentication key.', true) ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) ->param('teamId', '', new Text(0), 'APNS team ID.', true) @@ -1118,7 +1118,7 @@ App::patch('/v1/messaging/providers/:id/apns') ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -1130,7 +1130,7 @@ App::patch('/v1/messaging/providers/:id/apns') throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'apns' . ' ' . 'push'); } @@ -1234,18 +1234,18 @@ App::patch('/v1/messaging/providers/:id/general') ->label('sdk.response.model', Response::MODEL_PROVIDER) ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('credentials', '', new JSON(), 'Provider credentials.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, bool $enabled, array $credentials, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, array $credentials, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); } - if ($name) { + if (!empty($name)) { $provider->setAttribute('name', $name); } diff --git a/composer.lock b/composer.lock index 279847dedc..539c284fff 100644 --- a/composer.lock +++ b/composer.lock @@ -4145,16 +4145,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.0", + "version": "1.24.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6" + "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/3510b0a6274cc42f7219367cb3abfc123ffa09d6", - "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", + "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", "shasum": "" }, "require": { @@ -4186,22 +4186,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.1" }, - "time": "2023-09-07T20:46:32+00:00" + "time": "2023-09-18T12:18:02+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.28", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", - "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { @@ -4258,7 +4258,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.28" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -4266,7 +4266,7 @@ "type": "github" } ], - "time": "2023-09-12T14:36:20+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index c460d2b5d3..65def00b48 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -145,6 +145,21 @@ trait MessagingBase $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); } + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $providers[1]['$id'] . '/mailgun', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'name' => 'Mailgun2', + 'apiKey' => 'my-apikey', + 'domain' => 'my-domain', + 'isEuRegion' => true, + 'enabled' => false, + ]); + $providers[1] = $response['body']; + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Mailgun2', $response['body']['name']); + $this->assertEquals(false, $response['body']['enabled']); return $providers; } From f9030132a513f5a413944ec772c470ead3f5122c Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 17:38:29 +0530 Subject: [PATCH 46/72] messaging worker logic to send message to providers batch limit --- app/config/collections.php | 22 ++--- app/controllers/api/messaging.php | 3 +- app/init.php | 2 - app/workers/messaging.php | 87 +++++++++++++++---- composer.lock | 38 ++++---- .../Utopia/Response/Model/Message.php | 8 +- 6 files changed, 107 insertions(+), 53 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 7cc9db49cc..fb7548e260 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1534,6 +1534,17 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => 'processing', + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('data'), 'type' => Database::VAR_STRING, @@ -1589,17 +1600,6 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], - [ - '$id' => ID::custom('delivered'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ], [ '$id' => ID::custom('search'), 'type' => Database::VAR_STRING, diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index b2585418eb..ef17149aa4 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1307,7 +1307,7 @@ App::post('/v1/messaging/messages/email') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('providerId', '', new Text(128), 'Email Provider ID.') - ->param('to', [], new ArrayList(new Text(0)), 'Email Recepient.') + ->param('to', [], new ArrayList(new Text(0)), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(0), 'Email Subject.') ->param('content', '', new Text(0), 'Email Content.') ->param('from', '', new Text(0), 'Email from.', true) @@ -1333,6 +1333,7 @@ App::post('/v1/messaging/messages/email') 'from' => $from, 'html' => $html ], + 'status' => 'processing', 'search' => $subject . ' ' . $from, ])); diff --git a/app/init.php b/app/init.php index fd4117e799..ea01751be5 100644 --- a/app/init.php +++ b/app/init.php @@ -539,7 +539,6 @@ Database::addFilter( return Authorization::skip(fn() => $database ->find('targets', [ Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), ])); } ); @@ -555,7 +554,6 @@ Database::addFilter( $database ->find('subscribers', [ Query::equal('topicInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), ]) )); if (\count($targetIds) > 0) { diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 079ff3397b..65a519a98a 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -2,7 +2,10 @@ use Appwrite\Resque\Worker; use Utopia\CLI\Console; +use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Query; use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Adapters\SMS\Mock; use Utopia\Messaging\Adapters\SMS\Msg91; @@ -31,8 +34,8 @@ class MessagingV1 extends Worker protected ?PushAdapter $push = null; protected ?EmailAdapter $email = null; + protected ?Database $dbForProject = null; - protected ?string $from = null; public function getName(): string { @@ -86,33 +89,85 @@ class MessagingV1 extends Worker public function run(): void { $project = new Document($this->args['project']); + $this->dbForProject = $this->getProjectDB($project); - $dbForProject = $this->getProjectDB($project); - $message = new Document($this->args['message']); + $messageRecord = new Document($this->args['message']); - $providerId = $message->getAttribute('providerId'); - $providerRecord = $dbForProject->getDocument('providers', $providerId); + $providerId = $messageRecord->getAttribute('providerId'); + $providerRecord = $this->dbForProject->getDocument('providers', $providerId); - $provider = match ($providerRecord->getAttribute('type')) {//stubbbbbbed. + $this->processMessage($messageRecord, $providerRecord); + } + + private function processMessage(Document $messageRecord, Document $providerRecord): void + { + $provider = match ($providerRecord->getAttribute('type')) { 'sms' => $this->sms($providerRecord), 'push' => $this->push($providerRecord), 'email' => $this->email($providerRecord), default => null }; - // Query for the provider - // switch on provider name - // call function passing needed credentials returns required provider. + $recipientsId = $messageRecord->getAttribute('to'); - $message = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->buildSMSMessage($message->getArrayCopy()), - 'push' => $this->buildPushMessage($message->getArrayCopy()), - 'email' => $this->buildEmailMessage($message->getArrayCopy()), - default => null - }; + /** + * @var Document[] $recipients + */ + $recipients = []; - $provider->send($message); + $topics = $this->dbForProject->find('topics', [Query::equal('$id', $recipientsId)]); + foreach ($topics as $topic) { + $recipients = \array_merge($recipients, $topic->getAttribute('targets')); + } + + $users = $this->dbForProject->find('users', [Query::equal('$id', $recipientsId)]); + foreach ($users as $user) { + $recipients = \array_merge($recipients, $user->getAttribute('targets')); + } + + $targets = $this->dbForProject->find('targets', [Query::equal('$id', $recipientsId)]); + \array_merge($recipients, $targets); + + $identifiers = \array_map(function (Document $recipient) { + return $recipient->getAttribute('identifier'); + }, $recipients); + + $maxBatchSize = $provider->getMaxMessagesPerRequest(); + $batches = \array_chunk($identifiers, $maxBatchSize); + $message = $messageRecord->getArrayCopy(); + $deliveredTo = 0; + + foreach ($batches as $batch) { + $message['to'] = $batch; + $message = match ($providerRecord->getAttribute('type')) { + 'sms' => $this->buildSMSMessage($message), + 'push' => $this->buildPushMessage($message), + 'email' => $this->buildEmailMessage($message), + default => null + }; + try { + $provider->send($message); + $deliveredTo += \count($batch); + } catch (Exception $e) { + $deliveryErrors = $messageRecord->getAttribute('deliveryErrors'); + foreach ($batch as $identifier) { + $deliveryErrors[] = 'Failed to send message to target' . $identifier . ': ' . $e->getMessage(); + } + $messageRecord->setAttribute('deliveryErrors', $deliveryErrors); + } + } + + if (\count($messageRecord->getAttribute('deliveryErrors')) > 0) { + $messageRecord->setAttribute('status', 'failed'); + } else { + $messageRecord->setAttribute('status', 'sent'); + } + + $messageRecord->setAttribute('deliveredTo', $deliveredTo); + $messageRecord->setAttribute('deliveryTime', DateTime::now()); + + $this->dbForProject->updateDocument('messages', $messageRecord->getId(), $messageRecord); } public function shutdown(): void diff --git a/composer.lock b/composer.lock index a22f86efdd..14b07bdce7 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": "ce37f32b5c3c12e85d8d67bad35f57d7", + "content-hash": "6431be75373bf2e1bdbe2c638188d15f", "packages": [ { "name": "adhocore/jwt", @@ -2564,16 +2564,16 @@ }, { "name": "utopia-php/migration", - "version": "0.3.3", + "version": "0.3.4", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "45bd831ed9819994f05cb3b467c58f8155e27692" + "reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/45bd831ed9819994f05cb3b467c58f8155e27692", - "reference": "45bd831ed9819994f05cb3b467c58f8155e27692", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/ade836d61b3e1547bc9f0dc300ee75b24ab49f7a", + "reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a", "shasum": "" }, "require": { @@ -2616,9 +2616,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.3.3" + "source": "https://github.com/utopia-php/migration/tree/0.3.4" }, - "time": "2023-09-06T03:54:54+00:00" + "time": "2023-09-14T17:17:55+00:00" }, { "name": "utopia-php/mongo", @@ -4145,16 +4145,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.0", + "version": "1.24.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6" + "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/3510b0a6274cc42f7219367cb3abfc123ffa09d6", - "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", + "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", "shasum": "" }, "require": { @@ -4186,22 +4186,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.1" }, - "time": "2023-09-07T20:46:32+00:00" + "time": "2023-09-18T12:18:02+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.28", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", - "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { @@ -4258,7 +4258,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.28" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -4266,7 +4266,7 @@ "type": "github" } ], - "time": "2023-09-12T14:36:20+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 6eebbcd793..96c8c9b989 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -51,11 +51,11 @@ class Message extends Any 'default' => 0, 'example' => 1, ]) - ->addRule('delivered', [ - 'type' => self::TYPE_BOOLEAN, + ->addRule('status', [ + 'type' => self::TYPE_STRING, 'description' => 'Status of delivery.', - 'default' => false, - 'example' => true, + 'default' => 'processing', + 'example' => 'Message status can be one of the following: processing, sent, failed.', ]); } From 3456ad4e8cc3081ee3b7ec78e2d73f59d448b0df Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 17:52:25 +0530 Subject: [PATCH 47/72] fixes merge conflict issue --- app/controllers/api/teams.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index b4f14c9dbc..23d0d14c2a 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -389,7 +389,7 @@ App::post('/v1/teams/:teamId/memberships') ->inject('mails') ->inject('messaging') ->inject('events') - ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, string $from, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, EventPhone $messaging, Event $events) { + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, string $from, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, Messaging $messaging, Event $events) { $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); From 975b444761bc9affb901ae5941f65ee6ce08303a Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 20:51:03 +0530 Subject: [PATCH 48/72] fix test cases and bug fix in messaging worker --- app/controllers/api/account.php | 22 ++++++++++++++++++---- app/workers/messaging.php | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index cda5c030ed..8cce5a57f8 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1330,15 +1330,22 @@ App::post('/v1/account/sessions/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); + $target = $dbForProject->createDocument('targets', new Document([ + 'userId' => $user->getId(), + 'userInternalId' => $user->getInternalId(), + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'identifier' => $phone, + ])); + $messageDoc = $dbForProject->createDocument('messages', new Document([ - 'to' => [$phone], + 'to' => [$target->getId()], 'data' => [ 'content' => $message, 'from' => $from, ], 'providerId' => $provider->getId(), 'providerInternalId' => $provider->getInternalId(), - 'deliveryTime' => Datetime::now(), ])); $messaging @@ -2952,15 +2959,22 @@ App::post('/v1/account/verification/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); + $target = $dbForProject->createDocument('targets', new Document([ + 'userId' => $user->getId(), + 'userInternalId' => $user->getInternalId(), + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'identifier' => $user->getAttribute('phone'), + ])); + $messageDoc = $dbForProject->createDocument('messages', new Document([ - 'to' => [$user->getAttribute('phone')], + 'to' => [$target->getId()], 'data' => [ 'content' => $message, 'from' => $from, ], 'providerId' => $provider->getId(), 'providerInternalId' => $provider->getInternalId(), - 'deliveryTime' => Datetime::now(), ])); $messaging diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 65a519a98a..6fb1f42dc6 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -127,7 +127,7 @@ class MessagingV1 extends Worker } $targets = $this->dbForProject->find('targets', [Query::equal('$id', $recipientsId)]); - \array_merge($recipients, $targets); + $recipients = \array_merge($recipients, $targets); $identifiers = \array_map(function (Document $recipient) { return $recipient->getAttribute('identifier'); From 2fd7467e2ae463abdec8ec1bfe1a9b082c1a3b05 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 22:59:47 +0530 Subject: [PATCH 49/72] fix graphQL test --- app/config/services.php | 2 +- tests/e2e/Services/GraphQL/AccountTest.php | 22 ++++++++++++++++ tests/e2e/Services/GraphQL/Base.php | 29 ++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/app/config/services.php b/app/config/services.php index 6b57c01bff..cfefd60c8b 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -260,7 +260,7 @@ return [ 'sdk' => true, 'docs' => true, 'docsUrl' => 'https://appwrite.io/docs/server/messaging', - 'tests' => false, + 'tests' => true, 'optional' => true, 'icon' => '/images/services/messaging.png', ] diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 7fd70b5015..93c6b007ee 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -123,6 +123,28 @@ class AccountTest extends Scope public function testCreatePhoneVerification(): array { $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_PROVIDER); + $graphQLPayload = [ + 'query' => $query, + 'variables' => [ + 'providerId' => 'unique()', + 'name' => 'Mock', + 'provider' => 'mock', + 'type' => 'sms', + 'credentials' => [ + 'username' => 'username', + 'password' => 'password', + ], + 'default' => true, + ], + ]; + + $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $graphQLPayload); + $query = $this->getQuery(self::$CREATE_PHONE_VERIFICATION); $graphQLPayload = [ 'query' => $query, diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 3a4b88e2c2..bed34d4455 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -296,6 +296,8 @@ trait Base } '; + public static string $CREATE_PROVIDER = 'create_provider'; + public function getQuery(string $name): string { switch ($name) { @@ -1929,6 +1931,33 @@ trait Base } } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + case self::$CREATE_PROVIDER: + return 'mutation CreateGeneralProvider( + $providerId: String!, + $provider: String!, + $name: String!, + $type: String!, + $default: Boolean, + $enabled: Boolean, + $credentials: Json! + ) { + messagingCreateGeneralProvider( + providerId: $providerId, + provider: $provider, + name: $name, + type: $type, + default: $default, + enabled: $enabled, + credentials: $credentials + ) { + _id + name + provider + type + default + enabled + } + }'; } throw new \InvalidArgumentException('Invalid query type'); From dd14bbf785a0e4c3d663a69739d57393681e1dd7 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 23:02:53 +0530 Subject: [PATCH 50/72] lint fix --- tests/e2e/Services/GraphQL/Base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index bed34d4455..44cb0a0c55 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1931,7 +1931,7 @@ trait Base } } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; - case self::$CREATE_PROVIDER: + case self::$CREATE_PROVIDER: return 'mutation CreateGeneralProvider( $providerId: String!, $provider: String!, From 35d842171c2c0c9a92df697b137aae81f531d3a5 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 20 Sep 2023 23:37:10 +0530 Subject: [PATCH 51/72] review changes --- app/config/roles.php | 6 ---- app/controllers/api/teams.php | 10 +++++- app/controllers/api/users.php | 32 ++++--------------- app/init.php | 1 - .../Database/Validator/Queries/Providers.php | 2 ++ tests/e2e/Services/Account/AccountBase.php | 1 + .../Account/AccountCustomClientTest.php | 2 +- 7 files changed, 19 insertions(+), 35 deletions(-) diff --git a/app/config/roles.php b/app/config/roles.php index 579e13dfca..944fcf3577 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -62,12 +62,6 @@ $admins = [ 'rules.write', 'migrations.read', 'migrations.write', - 'targets.read', - 'targets.write', - 'providers.write', - 'providers.read', - 'messages.write', - 'messages.read', 'vcs.read', 'vcs.write', 'targets.read', diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 23d0d14c2a..08759cf39f 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -652,8 +652,16 @@ App::post('/v1/teams/:teamId/memberships') $message = $message->setParam('{{token}}', $url); $message = $message->render(); + $target = $dbForProject->createDocument('targets', new Document([ + 'userId' => $invitee->getId(), + 'userInternalId' => $invitee->getInternalId(), + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'identifier' => $phone, + ])); + $messageDoc = $dbForProject->createDocument('messages', new Document([ - 'to' => [$phone], + 'to' => [$target->getId()], 'data' => [ 'content' => $message, 'from' => $from, diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 1d88a04d11..9b2dc516cb 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -383,9 +383,8 @@ App::post('/v1/users/scrypt-modified') App::post('/v1/users/:userId/targets') ->desc('Create User Target') ->groups(['api', 'users']) - ->label('event', 'users.[userId].targets.[targetId].create') - ->label('audits.event', 'targets.create') - ->label('audits.resource', 'user/{response.userId}') + ->label('audits.event', 'users.targets.create') + ->label('audits.resource', 'target/response.$id') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -422,11 +421,6 @@ App::post('/v1/users/:userId/targets') $target = $dbForProject->createDocument('targets', new Document([ '$id' => $targetId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($userId)), - Permission::delete(Role::user($userId)), - ], 'providerId' => $providerId, 'providerInternalId' => $provider->getInternalId(), 'userId' => $userId, @@ -434,9 +428,6 @@ App::post('/v1/users/:userId/targets') 'identifier' => $identifier, ])); $dbForProject->deleteCachedDocument('users', $user->getId()); - $events - ->setParam('userId', $userId) - ->setParam('targetId', $targetId); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($target, Response::MODEL_TARGET); @@ -1207,9 +1198,8 @@ App::patch('/v1/users/:userId/prefs') App::patch('/v1/users/:userId/targets/:targetId/identifier') ->desc('Update user target\'s identifier') ->groups(['api', 'users']) - ->label('event', 'users.[userId].targets.[targetId].update') - ->label('audits.event', 'targets.update') - ->label('audits.resource', 'user/{response.userId}') + ->label('audits.event', 'users.targets.update') + ->label('audits.resource', 'target/{response.$id}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -1385,9 +1375,8 @@ App::delete('/v1/users/:userId') App::delete('/v1/users/:userId/targets/:targetId') ->desc('Delete user target') ->groups(['api', 'users']) - ->label('event', 'users.[userId].targets.[targetId].delete') - ->label('audits.event', 'targets.delete') - ->label('audits.resource', 'user/{response.userId}') + ->label('audits.event', 'users.targets.delete') + ->label('audits.resource', 'target/{request.$targetId}') ->label('scope', 'targets.write') ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'users') @@ -1417,15 +1406,6 @@ App::delete('/v1/users/:userId/targets/:targetId') $target = $dbForProject->deleteDocument('targets', $target->getId()); $dbForProject->deleteCachedDocument('users', $user->getId()); - $user = $dbForProject->getDocument('users', $userId); - - // clone user object to send to workers - $clone = clone $user; - - $events - ->setParam('userId', $userId) - ->setParam('targetId', $targetId) - ->setPayload($response->output($clone, Response::MODEL_USER)); $response->noContent(); }); diff --git a/app/init.php b/app/init.php index ea01751be5..a094acc7df 100644 --- a/app/init.php +++ b/app/init.php @@ -562,7 +562,6 @@ Database::addFilter( return []; } ); - /** * DB Formats */ diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php index 83dbf665f1..e72153734c 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php @@ -8,6 +8,8 @@ class Providers extends Base 'name', 'provider', 'type', + 'default', + 'enabled' ]; /** diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index b0959a3b0a..e64cf2c4ca 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -359,6 +359,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); + $this->assertEquals($response['headers']['status-code'], 200); $this->assertIsArray($response['body']['logs']); $this->assertNotEmpty($response['body']['logs']); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 9f922d63e2..5a177146a1 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -1013,7 +1013,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), ['from' => 'Appwrite']); + ]), ['from' => '+123456789']); $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); From b4de44c905f1a4ad33a5946d90406771410510ec Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 16:12:56 +0530 Subject: [PATCH 52/72] fix small bug in worker and send email endpoint --- app/controllers/api/messaging.php | 10 +++++----- app/workers/messaging.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index ef17149aa4..101ceb66dd 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1307,16 +1307,16 @@ App::post('/v1/messaging/messages/email') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('providerId', '', new Text(128), 'Email Provider ID.') - ->param('to', [], new ArrayList(new Text(0)), 'List of Topic IDs or List of User IDs or List of Target IDs.') - ->param('subject', '', new Text(0), 'Email Subject.') - ->param('content', '', new Text(0), 'Email Content.') - ->param('from', '', new Text(0), 'Email from.', true) + ->param('to', [], new ArrayList(new Text(65535)), 'List of Topic IDs or List of User IDs or List of Target IDs.') + ->param('subject', '', new Text(128), 'Email Subject.') + ->param('content', '', new Text(65407), 'Email Content.') + ->param('from', '', new Text(128), 'Email from.', true) ->param('html', false, new Boolean(false), 'Is content of type HTML', true) ->inject('dbForProject') ->inject('project') ->inject('messaging') ->inject('response') - ->action(function (string $providerId, array $to, string $subject, string $content, string $from, string $html, string $deliveryTime, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + ->action(function (string $providerId, array $to, string $subject, string $content, string $from, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 6fb1f42dc6..5b92bf59a0 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -76,7 +76,7 @@ class MessagingV1 extends Worker { $credentials = $record->getAttribute('credentials'); return match ($record->getAttribute('provider')) { - 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain']), + 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']), 'sendgrid' => new SendGrid($credentials['apiKey']), default => null }; From 342f1223655c10413571a7dfc8bc2db7b2b07d78 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 16:18:20 +0530 Subject: [PATCH 53/72] adds key auth to providers endpoint --- app/controllers/api/messaging.php | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 101ceb66dd..d9a57e03b3 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -26,7 +26,7 @@ App::get('/v1/messaging/providers') ->desc('List Providers') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'listProviders') ->label('sdk.description', '/docs/references/messaging/list-providers.md') @@ -68,7 +68,7 @@ App::get('/v1/messaging/providers/:id') ->desc('Get Provider') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'getProvider') ->label('sdk.description', '/docs/references/messaging/get-provider.md') @@ -97,7 +97,7 @@ App::post('/v1/messaging/providers/mailgun') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderMailgun') ->label('sdk.description', '/docs/references/messaging/create-provider-mailgun.md') @@ -157,7 +157,7 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderMailgun') ->label('sdk.description', '/docs/references/messaging/update-provider-mailgun.md') @@ -228,7 +228,7 @@ App::post('/v1/messaging/providers/sendgrid') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderSendgrid') ->label('sdk.description', '/docs/references/messaging/create-provider-sendgrid.md') @@ -283,7 +283,7 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderSendgrid') ->label('sdk.description', '/docs/references/messaging/update-provider-sendgrid.md') @@ -339,7 +339,7 @@ App::post('/v1/messaging/providers/msg91') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderMsg91') ->label('sdk.description', '/docs/references/messaging/create-provider-msg91.md') @@ -396,7 +396,7 @@ App::patch('/v1/messaging/providers/:id/msg91') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderMsg91') ->label('sdk.description', '/docs/references/messaging/update-provider-msg91.md') @@ -457,7 +457,7 @@ App::post('/v1/messaging/providers/telesign') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderTelesign') ->label('sdk.description', '/docs/references/messaging/create-provider-telesign.md') @@ -514,7 +514,7 @@ App::patch('/v1/messaging/providers/:id/telesign') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderTelesign') ->label('sdk.description', '/docs/references/messaging/update-provider-telesign.md') @@ -575,7 +575,7 @@ App::post('/v1/messaging/providers/textmagic') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderTextmagic') ->label('sdk.description', '/docs/references/messaging/create-provider-textmagic.md') @@ -632,7 +632,7 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderTextmagic') ->label('sdk.description', '/docs/references/messaging/update-provider-textmagic.md') @@ -693,7 +693,7 @@ App::post('/v1/messaging/providers/twilio') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderTwilio') ->label('sdk.description', '/docs/references/messaging/create-provider-twilio.md') @@ -750,7 +750,7 @@ App::patch('/v1/messaging/providers/:id/twilio') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderTwilio') ->label('sdk.description', '/docs/references/messaging/update-provider-twilio.md') @@ -811,7 +811,7 @@ App::post('/v1/messaging/providers/vonage') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderVonage') ->label('sdk.description', '/docs/references/messaging/create-provider-vonage.md') @@ -868,7 +868,7 @@ App::patch('/v1/messaging/providers/:id/vonage') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderVonage') ->label('sdk.description', '/docs/references/messaging/update-provider-vonage.md') @@ -932,7 +932,7 @@ App::post('/v1/messaging/providers/fcm') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderFCM') ->label('sdk.description', '/docs/references/messaging/create-provider-fcm.md') @@ -987,7 +987,7 @@ App::patch('/v1/messaging/providers/:id/fcm') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderFCM') ->label('sdk.description', '/docs/references/messaging/update-provider-fcm.md') @@ -1038,7 +1038,7 @@ App::post('/v1/messaging/providers/apns') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createProviderAPNS') ->label('sdk.description', '/docs/references/messaging/create-provider-apns.md') @@ -1101,7 +1101,7 @@ App::patch('/v1/messaging/providers/:id/apns') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderAPNS') ->label('sdk.description', '/docs/references/messaging/update-provider-apns.md') @@ -1171,7 +1171,7 @@ App::post('/v1/messaging/providers/general') ->label('audits.event', 'providers.create') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'createGeneralProvider') ->label('sdk.description', '/docs/references/messaging/create-general-provider.md') @@ -1225,7 +1225,7 @@ App::patch('/v1/messaging/providers/:id/general') ->label('audits.event', 'providers.update') ->label('audits.resource', 'providers/{response.$id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'updateProviderGeneral') ->label('sdk.description', '/docs/references/messaging/update-provider-general.md') @@ -1270,7 +1270,7 @@ App::delete('/v1/messaging/providers/:id') ->label('audits.event', 'providers.delete') ->label('audits.resource', 'providers/{request.id}') ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') ->label('sdk.method', 'deleteProvider') ->label('sdk.description', '/docs/references/messaging/delete-provider.md') From 3ebcfe548d56183c2c38989dab41405237686d23 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 16:26:53 +0530 Subject: [PATCH 54/72] Adds get message endpoint --- app/config/errors.php | 7 +++++++ app/controllers/api/messaging.php | 26 +++++++++++++++++++++++++- src/Appwrite/Extend/Exception.php | 3 +++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/app/config/errors.php b/app/config/errors.php index 8b2ccf810e..8001517d78 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -754,5 +754,12 @@ return [ 'name' => Exception::PROVIDER_INCORRECT_TYPE, 'description' => 'Provider with the requested ID is of incorrect type: ', 'code' => 400, + ], + + /** Message Errors */ + Exception::MESSAGE_NOT_FOUND => [ + 'name' => Exception::MESSAGE_NOT_FOUND, + 'description' => 'Message with the requested ID could not be found.', + 'code' => 404, ] ]; diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index d9a57e03b3..6c50578312 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -75,7 +75,7 @@ App::get('/v1/messaging/providers/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', null, new UID(), 'Provider ID.') + ->param('id', '', new UID(), 'Provider ID.') ->inject('dbForProject') ->inject('response') ->action(function (string $id, Database $dbForProject, Response $response) { @@ -1293,6 +1293,30 @@ App::delete('/v1/messaging/providers/:id') $response->noContent(); }); +App::get('/v1/messaging/messages/:id') + ->desc('Get Message') + ->groups(['api', 'messaging']) + ->label('scope', 'messages.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'getMessage') + ->label('sdk.description', '/docs/references/messaging/get-message.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->param('id', '', new UID(), 'Message ID.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, Database $dbForProject, Response $response) { + $message = $dbForProject->getDocument('message', $id); + + if ($message->isEmpty()) { + throw new Exception(Exception::MESSAGE_NOT_FOUND); + } + + $response->dynamic($message, Response::MODEL_MESSAGE); + }); + App::post('/v1/messaging/messages/email') ->desc('Send an email.') ->groups(['api', 'messaging']) diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 2b10b0cb51..cdd2538abb 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -230,6 +230,9 @@ class Exception extends \Exception public const PROVIDER_ALREADY_EXISTS = 'provider_already_exists'; public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; + /** Message */ + public const MESSAGE_NOT_FOUND = 'message_not_found'; + protected $type = ''; protected $errors = []; From 06a05a3358bfd2e2aa73dd5f6dbfd58f8dc6ea16 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 21:17:15 +0530 Subject: [PATCH 55/72] adds param messageId in send an email endpoint, tokenId as messageId in create phone session, membershipId as messageId in create team membership --- app/controllers/api/account.php | 2 ++ app/controllers/api/messaging.php | 6 +++++- app/controllers/api/teams.php | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 8cce5a57f8..e4ef089005 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1339,6 +1339,7 @@ App::post('/v1/account/sessions/phone') ])); $messageDoc = $dbForProject->createDocument('messages', new Document([ + '$id' => $token->getId(), 'to' => [$target->getId()], 'data' => [ 'content' => $message, @@ -2968,6 +2969,7 @@ App::post('/v1/account/verification/phone') ])); $messageDoc = $dbForProject->createDocument('messages', new Document([ + '$id' => $verification->getId(), 'to' => [$target->getId()], 'data' => [ 'content' => $message, diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 6c50578312..8014bb3f92 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1330,6 +1330,7 @@ App::post('/v1/messaging/messages/email') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('providerId', '', new Text(128), 'Email Provider ID.') ->param('to', [], new ArrayList(new Text(65535)), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(128), 'Email Subject.') @@ -1340,7 +1341,9 @@ App::post('/v1/messaging/messages/email') ->inject('project') ->inject('messaging') ->inject('response') - ->action(function (string $providerId, array $to, string $subject, string $content, string $from, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + ->action(function (string $messageId, string $providerId, array $to, string $subject, string $content, string $from, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1348,6 +1351,7 @@ App::post('/v1/messaging/messages/email') } $message = $dbForProject->createDocument('messages', new Document([ + '$id' => $messageId, 'providerId' => $provider->getId(), 'providerInternalId' => $provider->getInternalId(), 'to' => $to, diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 08759cf39f..4a697bedbb 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -661,6 +661,8 @@ App::post('/v1/teams/:teamId/memberships') ])); $messageDoc = $dbForProject->createDocument('messages', new Document([ + // Here membership ID is used as message ID so that it can be used in test cases to verify the message + '$id' => $membership->getId(), 'to' => [$target->getId()], 'data' => [ 'content' => $message, From d63eaf3ef010bbec9501ab86cba04e97eca8d900 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 21:49:40 +0530 Subject: [PATCH 56/72] fixes get message endpoint --- app/controllers/api/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 8014bb3f92..64da3919db 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1308,7 +1308,7 @@ App::get('/v1/messaging/messages/:id') ->inject('dbForProject') ->inject('response') ->action(function (string $id, Database $dbForProject, Response $response) { - $message = $dbForProject->getDocument('message', $id); + $message = $dbForProject->getDocument('messages', $id); if ($message->isEmpty()) { throw new Exception(Exception::MESSAGE_NOT_FOUND); From e2acb608fa7280e337f1fa91a31e5e8dca88eebf Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 22:16:02 +0530 Subject: [PATCH 57/72] fix tests with real sms providers --- .env | 6 +- app/controllers/api/messaging.php | 102 ------------------ docker-compose.yml | 4 + .../Account/AccountCustomClientTest.php | 62 +++++++---- tests/e2e/Services/GraphQL/AccountTest.php | 22 ++-- tests/e2e/Services/GraphQL/Base.php | 14 ++- 6 files changed, 71 insertions(+), 139 deletions(-) diff --git a/.env b/.env index 189095e9e5..9117fe9f3b 100644 --- a/.env +++ b/.env @@ -96,4 +96,8 @@ _APP_VCS_GITHUB_CLIENT_SECRET= _APP_VCS_GITHUB_WEBHOOK_SECRET= _APP_MIGRATIONS_FIREBASE_CLIENT_ID= _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET= -_APP_ASSISTANT_OPENAI_API_KEY= \ No newline at end of file +_APP_ASSISTANT_OPENAI_API_KEY= +_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID= +_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY= +_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM= +_APP_MESSAGE_SMS_PROVIDER_MSG91_TO= \ No newline at end of file diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 64da3919db..275051ecb0 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1162,108 +1162,6 @@ App::patch('/v1/messaging/providers/:id/apns') ->dynamic($provider, Response::MODEL_PROVIDER); }); -/** - * General Purpose Provider - */ -App::post('/v1/messaging/providers/general') - ->desc('Create General Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createGeneralProvider') - ->label('sdk.description', '/docs/references/messaging/create-general-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('provider', '', new Text(128), 'Provider Internal Name') - ->param('name', '', new Text(128), 'Provider name.') - ->param('type', '', new WhiteList(['push', 'email', 'sms']), 'Provider type.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('credentials', '', new JSON(), 'Provider credentials object.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $provider, string $name, string $type, bool $default, bool $enabled, array $credentials, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => $provider, - 'type' => $type, - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => $credentials, - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/general') - ->desc('Update General Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.update') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderGeneral') - ->label('sdk.description', '/docs/references/messaging/update-provider-general.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') - ->param('name', '', new Text(128), 'Provider name.', true) - ->param('enabled', null, new Boolean(), 'Set as enabled.', true) - ->param('credentials', '', new JSON(), 'Provider credentials.', true) - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, array $credentials, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); - - if ($provider->isEmpty()) { - throw new Exception(Exception::PROVIDER_NOT_FOUND); - } - - if (!empty($name)) { - $provider->setAttribute('name', $name); - } - - if ($enabled === true || $enabled === false) { - $provider->setAttribute('enabled', $enabled); - } - - if (!empty($credentials)) { - $provider->setAttribute('credentials', $credentials); - } - - $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); - - $response - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - App::delete('/v1/messaging/providers/:id') ->desc('Delete Provider') ->groups(['api', 'messaging']) diff --git a/docker-compose.yml b/docker-compose.yml index ac0fcabc8a..053042f81d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -186,6 +186,10 @@ services: - _APP_MIGRATIONS_FIREBASE_CLIENT_ID - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET - _APP_ASSISTANT_OPENAI_API_KEY + - _APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID + - _APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY + - _APP_MESSAGE_SMS_PROVIDER_MSG91_FROM + - _APP_MESSAGE_SMS_PROVIDER_MSG91_TO appwrite-realtime: entrypoint: realtime diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 5a177146a1..96f9b3774c 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -7,6 +7,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; +use Utopia\App; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -742,20 +743,27 @@ class AccountCustomClientTest extends Scope public function testCreatePhone(): array { - $number = '+123456789'; - $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/general', \array_merge([ + $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); + $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); + $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); + $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); + + if($to === '' || $from === '' || $authKey === '' || $senderId === '') { + $this->markTestSkipped('SMS provider not configured'); + } + + $number = $to; + $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/msg91', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ 'providerId' => 'unique()', - 'name' => 'Mock', - 'provider' => 'mock', + 'name' => 'Sms provider', + 'provider' => 'msg91', 'type' => 'sms', - 'credentials' => [ - 'username' => 'username', - 'password' => 'password', - ], + 'senderId' => $senderId, + 'authKey' => $authKey, 'default' => true, ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -769,7 +777,7 @@ class AccountCustomClientTest extends Scope ]), [ 'userId' => ID::unique(), 'phone' => $number, - 'from' => $number, + 'from' => $from, ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -778,6 +786,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); $userId = $response['body']['userId']; + $messageId = $response['body']['$id']; /** * Test for FAILURE @@ -794,17 +803,19 @@ class AccountCustomClientTest extends Scope \sleep(5); - $smsRequest = $this->getLastRequest(); + $message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $messageId, [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); - $this->assertEquals('http://request-catcher:5000/mock-sms', $smsRequest['url']); - $this->assertEquals('Appwrite Mock Message Sender', $smsRequest['headers']['User-Agent']); - $this->assertEquals('username', $smsRequest['headers']['X-Username']); - $this->assertEquals('password', $smsRequest['headers']['X-Key']); - $this->assertEquals('POST', $smsRequest['method']); - $this->assertEquals('+123456789', $smsRequest['data']['from']); - $this->assertEquals($number, $smsRequest['data']['to']); + $this->assertEquals(200, $message['headers']['status-code']); + $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(0, \count($message['body']['deliveryErrors'])); - $data['token'] = $smsRequest['data']['message']; + + $data['token'] = $message['body']['data']['content']; $data['id'] = $userId; $data['number'] = $number; @@ -1013,7 +1024,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), ['from' => '+123456789']); + ]), ['from' => App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM')]); $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); @@ -1022,10 +1033,19 @@ class AccountCustomClientTest extends Scope \sleep(2); - $smsRequest = $this->getLastRequest(); + $message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $response['body']['$id'], [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + + $this->assertEquals(200, $message['headers']['status-code']); + $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(0, \count($message['body']['deliveryErrors'])); return \array_merge($data, [ - 'token' => $smsRequest['data']['message'] + 'token' => $message['body']['data']['content'] ]); } diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 93c6b007ee..0366c2f359 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -6,6 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; +use Utopia\App; use Utopia\Database\Helpers\ID; class AccountTest extends Scope @@ -122,24 +123,31 @@ class AccountTest extends Scope */ public function testCreatePhoneVerification(): array { + $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); + $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); + $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); + $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); + + if($to === '' || $from === '' || $authKey === '' || $senderId === '') { + $this->markTestSkipped('SMS provider not configured'); + } + $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_PROVIDER); $graphQLPayload = [ 'query' => $query, 'variables' => [ 'providerId' => 'unique()', - 'name' => 'Mock', - 'provider' => 'mock', + 'name' => 'Sms Provider', + 'provider' => 'msg91', 'type' => 'sms', - 'credentials' => [ - 'username' => 'username', - 'password' => 'password', - ], + 'senderId' => $senderId, + 'authKey' => $authKey, 'default' => true, ], ]; - $this->client->call(Client::METHOD_POST, '/graphql', [ + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $this->getProject()['apiKey'], diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 44cb0a0c55..7f163fdffb 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1932,23 +1932,21 @@ trait Base } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$CREATE_PROVIDER: - return 'mutation CreateGeneralProvider( + return 'mutation createProviderMsg91( $providerId: String!, - $provider: String!, $name: String!, - $type: String!, + $senderId: String!, + $authKey: String! $default: Boolean, $enabled: Boolean, - $credentials: Json! ) { - messagingCreateGeneralProvider( + messagingCreateProviderMsg91( providerId: $providerId, - provider: $provider, name: $name, - type: $type, + senderId: $senderId, + authKey: $authKey default: $default, enabled: $enabled, - credentials: $credentials ) { _id name From df6466a1d35d00678644cf06c2e52bc5131a662d Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 21 Sep 2023 22:20:56 +0530 Subject: [PATCH 58/72] lint fix --- tests/e2e/Services/Account/AccountCustomClientTest.php | 2 +- tests/e2e/Services/GraphQL/AccountTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 96f9b3774c..77d8662ba4 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -748,7 +748,7 @@ class AccountCustomClientTest extends Scope $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - if($to === '' || $from === '' || $authKey === '' || $senderId === '') { + if ($to === '' || $from === '' || $authKey === '' || $senderId === '') { $this->markTestSkipped('SMS provider not configured'); } diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 0366c2f359..aa60d2d81b 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -128,10 +128,10 @@ class AccountTest extends Scope $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - if($to === '' || $from === '' || $authKey === '' || $senderId === '') { + if ($to === '' || $from === '' || $authKey === '' || $senderId === '') { $this->markTestSkipped('SMS provider not configured'); } - + $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_PROVIDER); $graphQLPayload = [ From a0858ccc4ec493e88b5f9bf27b1240632f3e409b Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Tue, 26 Sep 2023 13:12:44 +0530 Subject: [PATCH 59/72] adds message description, options to mailgun provider --- app/config/collections.php | 22 ++++++++++++++++ app/controllers/api/messaging.php | 25 ++++++++++++++----- composer.lock | 12 ++++----- .../Utopia/Response/Model/Message.php | 7 ++++++ .../Utopia/Response/Model/Provider.php | 17 +++++++++++++ .../e2e/Services/Messaging/MessagingBase.php | 1 + 6 files changed, 72 insertions(+), 12 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index fb7548e260..5506467cc4 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1449,6 +1449,17 @@ $commonCollections = [ 'array' => false, 'filters' => ['json', 'encrypt'], ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], [ '$id' => ID::custom('search'), 'type' => Database::VAR_STRING, @@ -1534,6 +1545,17 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('description'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('status'), 'type' => Database::VAR_STRING, diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 275051ecb0..45c2760aba 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -108,12 +108,13 @@ App::post('/v1/messaging/providers/mailgun') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('isEuRegion', false, new Boolean(), 'Set as eu region.', true) + ->param('isEuRegion', false, new Boolean(), 'Set as EU region.', true) + ->param('from', '', new Text(256), 'Sender Email Address.') ->param('apiKey', '', new Text(0), 'Mailgun API Key.') ->param('domain', '', new Text(0), 'Mailgun Domain.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, bool $isEuRegion, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ @@ -129,6 +130,9 @@ App::post('/v1/messaging/providers/mailgun') 'domain' => $domain, 'isEuRegion' => $isEuRegion, ], + 'options' => [ + 'from' => $from, + ] ]); // Check if a default provider exists, if not, set this one as default @@ -167,12 +171,13 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->param('id', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) - ->param('isEuRegion', false, new Boolean(), 'Set as eu region.', true) + ->param('isEuRegion', null, new Boolean(), 'Set as eu region.', true) + ->param('from', '', new Text(256), 'Sender Email Address.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) ->param('domain', '', new Text(0), 'Mailgun Domain.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, bool $isEuRegion, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $id, string $name, ?bool $enabled, ?bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $id); if ($provider->isEmpty()) { @@ -198,6 +203,12 @@ App::patch('/v1/messaging/providers/:id/mailgun') ]); } + if (!empty($from)) { + $provider->setAttribute('options', [ + 'from' => $from, + ]); + } + if ($enabled === true || $enabled === false) { $provider->setAttribute('enabled', $enabled); } @@ -1232,6 +1243,7 @@ App::post('/v1/messaging/messages/email') ->param('providerId', '', new Text(128), 'Email Provider ID.') ->param('to', [], new ArrayList(new Text(65535)), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(128), 'Email Subject.') + ->param('description', '', new Text(256), 'Description for Message.') ->param('content', '', new Text(65407), 'Email Content.') ->param('from', '', new Text(128), 'Email from.', true) ->param('html', false, new Boolean(false), 'Is content of type HTML', true) @@ -1239,7 +1251,7 @@ App::post('/v1/messaging/messages/email') ->inject('project') ->inject('messaging') ->inject('response') - ->action(function (string $messageId, string $providerId, array $to, string $subject, string $content, string $from, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + ->action(function (string $messageId, string $providerId, array $to, string $subject, string $description, string $content, string $from, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; $provider = $dbForProject->getDocument('providers', $providerId); @@ -1257,7 +1269,8 @@ App::post('/v1/messaging/messages/email') 'subject' => $subject, 'content' => $content, 'from' => $from, - 'html' => $html + 'html' => $html, + 'description' => $description, ], 'status' => 'processing', 'search' => $subject . ' ' . $from, diff --git a/composer.lock b/composer.lock index 14b07bdce7..e739e122c9 100644 --- a/composer.lock +++ b/composer.lock @@ -1318,16 +1318,16 @@ }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { @@ -1364,9 +1364,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 96c8c9b989..2f75997048 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -56,6 +56,13 @@ class Message extends Any 'description' => 'Status of delivery.', 'default' => 'processing', 'example' => 'Message status can be one of the following: processing, sent, failed.', + ]) + ->addRule('description', [ + 'type' => self::TYPE_STRING, + 'description' => 'Message description.', + 'required' => false, + 'default' => '', + 'example' => 'Welcome Email.', ]); } diff --git a/src/Appwrite/Utopia/Response/Model/Provider.php b/src/Appwrite/Utopia/Response/Model/Provider.php index e33e5a253d..552e9783e8 100644 --- a/src/Appwrite/Utopia/Response/Model/Provider.php +++ b/src/Appwrite/Utopia/Response/Model/Provider.php @@ -45,6 +45,23 @@ class Provider extends Model 'description' => 'Type of provider.', 'default' => '', 'example' => 'sms', + ]) + ->addRule('credentials', [ + 'type' => self::TYPE_JSON, + 'description' => 'Provider credentials.', + 'default' => [], + 'example' => [ + 'key' => '123456789' + ], + ]) + ->addRule('options', [ + 'type' => self::TYPE_JSON, + 'description' => 'Provider options.', + 'default' => [], + 'required' => false, + 'example' => [ + 'from' => 'sender-email@mydomain' + ], ]); } diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 65def00b48..59007cce15 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -19,6 +19,7 @@ trait MessagingBase 'name' => 'Mailgun1', 'apiKey' => 'my-apikey', 'domain' => 'my-domain', + 'from' => 'sender-email@my-domain', ], 'twilio' => [ 'providerId' => 'unique()', From 234f7f003be046fb8c18696c1c84f1c00e339364 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 27 Sep 2023 18:58:00 +0530 Subject: [PATCH 60/72] updated test cases for msg91 provider, moves worker to use provider from settings --- .env | 7 ++- app/config/collections.php | 2 +- app/controllers/api/account.php | 6 +- app/controllers/api/messaging.php | 17 +++--- app/controllers/api/teams.php | 3 +- app/workers/messaging.php | 55 +++++++++---------- docker-compose.yml | 5 ++ src/Appwrite/Event/Messaging.php | 20 +++---- .../Account/AccountCustomClientTest.php | 1 + tests/e2e/Services/GraphQL/AccountTest.php | 1 + tests/e2e/Services/GraphQL/Base.php | 2 + .../e2e/Services/Messaging/MessagingBase.php | 1 + 12 files changed, 67 insertions(+), 53 deletions(-) diff --git a/.env b/.env index 9117fe9f3b..7f41937b89 100644 --- a/.env +++ b/.env @@ -100,4 +100,9 @@ _APP_ASSISTANT_OPENAI_API_KEY= _APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID= _APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY= _APP_MESSAGE_SMS_PROVIDER_MSG91_FROM= -_APP_MESSAGE_SMS_PROVIDER_MSG91_TO= \ No newline at end of file +_APP_MESSAGE_SMS_PROVIDER_MSG91_TO= +_APP_MESSAGE_SMS_PROVIDER_MAILGUN_API_KEY= +_APP_MESSAGE_SMS_PROVIDER_MAILGUN_DOMAIN= +_APP_MESSAGE_SMS_PROVIDER_MAILGUN_FROM= +_APP_MESSAGE_SMS_PROVIDER_MAILGUN_RECEIVER_EMAIL= +_APP_MESSAGE_SMS_PROVIDER_MAILGUN_IS_EU_REGION= diff --git a/app/config/collections.php b/app/config/collections.php index 5506467cc4..9aec38a3d9 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1456,7 +1456,7 @@ $commonCollections = [ 'size' => 16384, 'signed' => true, 'required' => false, - 'default' => null, + 'default' => [], 'array' => false, 'filters' => ['json'], ], diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index e4ef089005..7115bf5686 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1343,14 +1343,13 @@ App::post('/v1/account/sessions/phone') 'to' => [$target->getId()], 'data' => [ 'content' => $message, - 'from' => $from, ], 'providerId' => $provider->getId(), 'providerInternalId' => $provider->getInternalId(), ])); $messaging - ->setMessage($messageDoc) + ->setMessageId($messageDoc->getId()) ->setProject($project) ->trigger(); @@ -2973,14 +2972,13 @@ App::post('/v1/account/verification/phone') 'to' => [$target->getId()], 'data' => [ 'content' => $message, - 'from' => $from, ], 'providerId' => $provider->getId(), 'providerInternalId' => $provider->getInternalId(), ])); $messaging - ->setMessage($messageDoc) + ->setMessageId($messageDoc->getId()) ->setProject($project) ->trigger(); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 45c2760aba..9abf1d492f 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -262,6 +262,7 @@ App::post('/v1/messaging/providers/sendgrid') 'type' => 'email', 'default' => $default, 'enabled' => $enabled, + 'options' => [], 'search' => $providerId . ' ' . $name . ' ' . 'sendgrid' . ' ' . 'email', 'credentials' => [ 'apiKey' => $apiKey, @@ -361,11 +362,12 @@ App::post('/v1/messaging/providers/msg91') ->param('name', '', new Text(128), 'Provider name.') ->param('default', false, new Boolean(), 'Set as default provider.', true) ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('from', '', new Text(256), 'Sender Number.') ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $from, string $senderId, string $authKey, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $provider = new Document([ '$id' => $providerId, @@ -379,6 +381,9 @@ App::post('/v1/messaging/providers/msg91') 'senderId' => $senderId, 'authKey' => $authKey, ], + 'options' => [ + 'from' => $from, + ] ]); // Check if a default provider exists, if not, set this one as default @@ -1243,15 +1248,14 @@ App::post('/v1/messaging/messages/email') ->param('providerId', '', new Text(128), 'Email Provider ID.') ->param('to', [], new ArrayList(new Text(65535)), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(128), 'Email Subject.') - ->param('description', '', new Text(256), 'Description for Message.') + ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(65407), 'Email Content.') - ->param('from', '', new Text(128), 'Email from.', true) ->param('html', false, new Boolean(false), 'Is content of type HTML', true) ->inject('dbForProject') ->inject('project') ->inject('messaging') ->inject('response') - ->action(function (string $messageId, string $providerId, array $to, string $subject, string $description, string $content, string $from, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + ->action(function (string $messageId, string $providerId, array $to, string $subject, string $description, string $content, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; $provider = $dbForProject->getDocument('providers', $providerId); @@ -1268,16 +1272,15 @@ App::post('/v1/messaging/messages/email') 'data' => [ 'subject' => $subject, 'content' => $content, - 'from' => $from, 'html' => $html, 'description' => $description, ], 'status' => 'processing', - 'search' => $subject . ' ' . $from, + 'search' => $messageId . ' ' . $description . ' ' . $subject, ])); $messaging - ->setMessage($message) + ->setMessageId($message->getId()) ->setProject($project) ->trigger(); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 4a697bedbb..18c8118cb6 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -666,7 +666,6 @@ App::post('/v1/teams/:teamId/memberships') 'to' => [$target->getId()], 'data' => [ 'content' => $message, - 'from' => $from, ], 'providerId' => $provider->getId(), 'providerInternalId' => $provider->getInternalId(), @@ -674,7 +673,7 @@ App::post('/v1/teams/:teamId/memberships') ])); $messaging - ->setMessage($messageDoc) + ->setMessageId($messageDoc->getId()) ->setProject($project) ->trigger(); } diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 5b92bf59a0..b5dc79917d 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -91,7 +91,7 @@ class MessagingV1 extends Worker $project = new Document($this->args['project']); $this->dbForProject = $this->getProjectDB($project); - $messageRecord = new Document($this->args['message']); + $messageRecord = $this->dbForProject->getDocument('messages', $this->args['messageId']); $providerId = $messageRecord->getAttribute('providerId'); $providerRecord = $this->dbForProject->getDocument('providers', $providerId); @@ -135,15 +135,14 @@ class MessagingV1 extends Worker $maxBatchSize = $provider->getMaxMessagesPerRequest(); $batches = \array_chunk($identifiers, $maxBatchSize); - $message = $messageRecord->getArrayCopy(); $deliveredTo = 0; foreach ($batches as $batch) { - $message['to'] = $batch; + $messageRecord->setAttribute('to', $batch); $message = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->buildSMSMessage($message), - 'push' => $this->buildPushMessage($message), - 'email' => $this->buildEmailMessage($message), + 'sms' => $this->buildSMSMessage($messageRecord, $providerRecord), + 'push' => $this->buildPushMessage($messageRecord), + 'email' => $this->buildEmailMessage($messageRecord, $providerRecord), default => null }; try { @@ -163,7 +162,7 @@ class MessagingV1 extends Worker } else { $messageRecord->setAttribute('status', 'sent'); } - + $messageRecord->setAttribute('to', $recipientsId); $messageRecord->setAttribute('deliveredTo', $deliveredTo); $messageRecord->setAttribute('deliveryTime', DateTime::now()); @@ -174,37 +173,37 @@ class MessagingV1 extends Worker { } - private function buildEmailMessage($data): Email + private function buildEmailMessage($message, $provider): Email { - $from = $data['data']['from']; - $to = $data['to']; - $subject = $data['data']['subject']; - $content = $data['data']['content']; - $html = $data['data']['html']; + $from = $provider['options']['from']; + $to = $message['to']; + $subject = $message['data']['subject']; + $content = $message['data']['content']; + $html = $message['data']['html']; return new Email(to: $to, subject: $subject, content: $content, from: $from, html: $html); } - private function buildSMSMessage($data): SMS + private function buildSMSMessage($message, $provider): SMS { - $to = $data['to']; - $content = $data['data']['content']; - $from = $data['data']['from']; + $to = $message['to']; + $content = $message['data']['content']; + $from = $provider['options']['from']; return new SMS($to, $content, $from); } - private function buildPushMessage($data): Push + private function buildPushMessage($message): Push { - $to = $data['to']; - $title = $data['data']['title']; - $body = $data['data']['body']; - $data = $data['data']['data']; - $action = $data['data']['action']; - $sound = $data['data']['sound']; - $icon = $data['data']['icon']; - $color = $data['data']['color']; - $tag = $data['data']['tag']; - $badge = $data['data']['badge']; + $to = $message['to']; + $title = $message['data']['title']; + $body = $message['data']['body']; + $data = $message['data']['data']; + $action = $message['data']['action']; + $sound = $message['data']['sound']; + $icon = $message['data']['icon']; + $color = $message['data']['color']; + $tag = $message['data']['tag']; + $badge = $message['data']['badge']; return new Push($to, $title, $body, $data, $action, $sound, $icon, $color, $tag, $badge); } } diff --git a/docker-compose.yml b/docker-compose.yml index 053042f81d..b60406369b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -190,6 +190,11 @@ services: - _APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY - _APP_MESSAGE_SMS_PROVIDER_MSG91_FROM - _APP_MESSAGE_SMS_PROVIDER_MSG91_TO + - _APP_MESSAGE_SMS_PROVIDER_MAILGUN_API_KEY + - _APP_MESSAGE_SMS_PROVIDER_MAILGUN_DOMAIN + - _APP_MESSAGE_SMS_PROVIDER_MAILGUN_FROM + - _APP_MESSAGE_SMS_PROVIDER_MAILGUN_RECEIVER_EMAIL + - _APP_MESSAGE_SMS_PROVIDER_MAILGUN_IS_EU_REGION appwrite-realtime: entrypoint: realtime diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index 9616f93a21..1df75dfedf 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -7,7 +7,7 @@ use Utopia\Database\Document; class Messaging extends Event { - protected ?Document $message = null; + protected ?string $messageId = null; public function __construct() { @@ -17,26 +17,26 @@ class Messaging extends Event /** - * Sets message record for the messaging event. + * Sets message ID for the messaging event. * - * @param Document $message + * @param string $message * @return self */ - public function setMessage(Document $message): self + public function setMessageId(string $messageId): self { - $this->message = $message; + $this->messageId = $messageId; return $this; } /** - * Returns set message for the messaging event. + * Returns set message ID for the messaging event. * - * @return Document + * @return string */ - public function getMessage(): Document + public function getMessageId(): string { - return $this->message; + return $this->messageId; } /** @@ -50,7 +50,7 @@ class Messaging extends Event return Resque::enqueue($this->queue, $this->class, [ 'project' => $this->project, 'user' => $this->user, - 'message' => $this->message, + 'messageId' => $this->messageId, ]); } } diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 77d8662ba4..96f2b12308 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -765,6 +765,7 @@ class AccountCustomClientTest extends Scope 'senderId' => $senderId, 'authKey' => $authKey, 'default' => true, + 'from' => $from, ]); $this->assertEquals(201, $response['headers']['status-code']); /** diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index aa60d2d81b..5970883dbe 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -141,6 +141,7 @@ class AccountTest extends Scope 'name' => 'Sms Provider', 'provider' => 'msg91', 'type' => 'sms', + 'from' => $from, 'senderId' => $senderId, 'authKey' => $authKey, 'default' => true, diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 7f163fdffb..c670f8e17c 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1935,6 +1935,7 @@ trait Base return 'mutation createProviderMsg91( $providerId: String!, $name: String!, + $from: String!, $senderId: String!, $authKey: String! $default: Boolean, @@ -1943,6 +1944,7 @@ trait Base messagingCreateProviderMsg91( providerId: $providerId, name: $name, + from: $from, senderId: $senderId, authKey: $authKey default: $default, diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 59007cce15..bbc8b56693 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -44,6 +44,7 @@ trait MessagingBase 'name' => 'Ms91-1', 'senderId' => 'my-senderid', 'authKey' => 'my-authkey', + 'from' => '+123456789' ], 'vonage' => [ 'providerId' => 'unique()', From 48b91e39a81ef6a54ef7a8d4127090065911cd0d Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 4 Oct 2023 16:15:59 +0530 Subject: [PATCH 61/72] review changes --- app/config/collections.php | 7 + app/controllers/api/account.php | 49 +- app/controllers/api/messaging.php | 1376 ++++++++--------- app/controllers/api/users.php | 1 - app/workers/messaging.php | 156 +- composer.json | 2 +- composer.lock | 95 +- src/Appwrite/Event/Messaging.php | 1 - .../Account/AccountCustomClientTest.php | 8 +- tests/e2e/Services/GraphQL/AccountTest.php | 6 +- .../e2e/Services/Messaging/MessagingBase.php | 4 +- 11 files changed, 851 insertions(+), 854 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 9aec38a3d9..1a56b160c6 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1934,6 +1934,13 @@ $commonCollections = [ 'attributes' => ['providerInternalId'], 'lengths' => [], 'orders' => [], + ], + [ + '$id' => ID::custom('_key_identifier'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['identifier'], + 'lengths' => [], + 'orders' => [], ] ], ], diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 7115bf5686..228a0621cd 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1230,7 +1230,6 @@ App::post('/v1/account/sessions/phone') ->label('abuse-key', 'url:{url},phone:{param-phone}') ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.') - ->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true) ->inject('request') ->inject('response') ->inject('user') @@ -1239,9 +1238,9 @@ App::post('/v1/account/sessions/phone') ->inject('events') ->inject('messaging') ->inject('locale') - ->action(function (string $userId, string $phone, string $from, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, Messaging $messaging, Locale $locale) { + ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $events, Messaging $messaging, Locale $locale) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true, false]), + Query::equal('default', [true]), Query::equal('type', ['sms']) ])); if ($provider === false || $provider->isEmpty()) { @@ -1330,13 +1329,20 @@ App::post('/v1/account/sessions/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); - $target = $dbForProject->createDocument('targets', new Document([ - 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), - 'providerId' => $provider->getId(), - 'providerInternalId' => $provider->getInternalId(), - 'identifier' => $phone, - ])); + $target = $dbForProject->findOne('targets', [ + Query::equal('identifier', [$phone]), + Query::equal('providerInternalId', [$provider->getInternalId()]) + ]); + + if (!$target) { + $target = $dbForProject->createDocument('targets', new Document([ + 'userId' => $user->getId(), + 'userInternalId' => $user->getInternalId(), + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'identifier' => $phone, + ])); + } $messageDoc = $dbForProject->createDocument('messages', new Document([ '$id' => $token->getId(), @@ -2899,7 +2905,6 @@ App::post('/v1/account/verification/phone') ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) ->label('abuse-key', 'userId:{userId}') - ->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true) ->inject('request') ->inject('response') ->inject('user') @@ -2908,9 +2913,9 @@ App::post('/v1/account/verification/phone') ->inject('messaging') ->inject('project') ->inject('locale') - ->action(function (string $from, Request $request, Response $response, Document $user, Database $dbForProject, Event $events, Messaging $messaging, Document $project, Locale $locale) { + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $events, Messaging $messaging, Document $project, Locale $locale) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true, false]), + Query::equal('default', [true]), Query::equal('type', ['sms']) ])); if ($provider === false || $provider->isEmpty()) { @@ -2959,13 +2964,17 @@ App::post('/v1/account/verification/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); - $target = $dbForProject->createDocument('targets', new Document([ - 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), - 'providerId' => $provider->getId(), - 'providerInternalId' => $provider->getInternalId(), - 'identifier' => $user->getAttribute('phone'), - ])); + $target = $dbForProject->findOne('targets', [Query::equal('identifier', [$user->getAttribute('phone')]), Query::equal('providerInternalId', [$provider->getInternalId()])]); + + if (!$target) { + $target = $dbForProject->createDocument('targets', new Document([ + 'userId' => $user->getId(), + 'userInternalId' => $user->getInternalId(), + 'providerId' => $provider->getId(), + 'providerInternalId' => $provider->getInternalId(), + 'identifier' => $user->getAttribute('phone'), + ])); + } $messageDoc = $dbForProject->createDocument('messages', new Document([ '$id' => $verification->getId(), diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 9abf1d492f..f2a61cde36 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -22,6 +22,541 @@ use Utopia\Validator\JSON; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; +App::post('/v1/messaging/providers/mailgun') + ->desc('Create Mailgun Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createMailgunProvider') + ->label('sdk.description', '/docs/references/messaging/create-mailgun-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('isEuRegion', false, new Boolean(), 'Set as EU region.', true) + ->param('from', '', new Text(256), 'Sender Email Address.') + ->param('apiKey', '', new Text(0), 'Mailgun API Key.') + ->param('domain', '', new Text(0), 'Mailgun Domain.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'mailgun', + 'type' => 'email', + 'default' => $default, + 'enabled' => $enabled, + 'search' => $providerId . ' ' . $name . ' ' . 'mailgun' . ' ' . 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + 'domain' => $domain, + 'isEuRegion' => $isEuRegion, + ], + 'options' => [ + 'from' => $from, + ] + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['email']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/sendgrid') + ->desc('Create Sendgrid Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createSendgridProvider') + ->label('sdk.description', '/docs/references/messaging/create-sengrid-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('apiKey', '', new Text(0), 'Sendgrid API key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'sendgrid', + 'type' => 'email', + 'default' => $default, + 'enabled' => $enabled, + 'options' => [], + 'search' => $providerId . ' ' . $name . ' ' . 'sendgrid' . ' ' . 'email', + 'credentials' => [ + 'apiKey' => $apiKey, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['sms']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/msg91') + ->desc('Create Msg91 Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createMsg91Provider') + ->label('sdk.description', '/docs/references/messaging/create-msg91-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('from', '', new Text(256), 'Sender Number.') + ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') + ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $from, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'msg91', + 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'msg91' . ' ' . 'sms', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'senderId' => $senderId, + 'authKey' => $authKey, + ], + 'options' => [ + 'from' => $from, + ] + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['sms']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); +App::post('/v1/messaging/providers/telesign') + ->desc('Create Telesign Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createTelesignProvider') + ->label('sdk.description', '/docs/references/messaging/create-telesign-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('username', '', new Text(0), 'Telesign username.') + ->param('password', '', new Text(0), 'Telesign password.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'telesign', + 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'telesign' . ' ' . 'sms', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'username' => $username, + 'password' => $password, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['sms']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/textmagic') + ->desc('Create Textmagic Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createTextmagicProvider') + ->label('sdk.description', '/docs/references/messaging/create-textmagic-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('username', '', new Text(0), 'Textmagic username.') + ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'text-magic', + 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'text-magic' . ' ' . 'sms', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'username' => $username, + 'apiKey' => $apiKey, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['sms']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/twilio') + ->desc('Create Twilio Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createTwilioProvider') + ->label('sdk.description', '/docs/references/messaging/create-twilio-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') + ->param('authToken', '', new Text(0), 'Twilio authentication token.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'twilio', + 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'twilio' . ' ' . 'sms', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'accountSid' => $accountSid, + 'authToken' => $authToken, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['sms']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/vonage') + ->desc('Create Vonage Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createVonageProvider') + ->label('sdk.description', '/docs/references/messaging/create-vonage-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('apiKey', '', new Text(0), 'Vonage API key.') + ->param('apiSecret', '', new Text(0), 'Vonage API secret.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'vonage', + 'type' => 'sms', + 'search' => $providerId . ' ' . $name . ' ' . 'vonage' . ' ' . 'sms', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'apiKey' => $apiKey, + 'apiSecret' => $apiSecret, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['sms']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/fcm') + ->desc('Create FCM Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createFCMProvider') + ->label('sdk.description', '/docs/references/messaging/create-fcm-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('serverKey', '', new Text(0), 'FCM Server Key.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $serverKey, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'fcm', + 'type' => 'push', + 'search' => $providerId . ' ' . $name . ' ' . 'fcm' . ' ' . 'push', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'serverKey' => $serverKey, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['pushq']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + +App::post('/v1/messaging/providers/apns') + ->desc('Create APNS Provider') + ->groups(['api', 'messaging']) + ->label('audits.event', 'providers.create') + ->label('audits.resource', 'providers/{response.$id}') + ->label('scope', 'providers.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'createAPNSProvider') + ->label('sdk.description', '/docs/references/messaging/create-apns-provider.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Provider name.') + ->param('default', false, new Boolean(), 'Set as default provider.', true) + ->param('enabled', true, new Boolean(), 'Set as enabled.', true) + ->param('authKey', '', new Text(0), 'APNS authentication key.') + ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') + ->param('teamId', '', new Text(0), 'APNS team ID.') + ->param('bundleId', '', new Text(0), 'APNS bundle ID.') + ->param('endpoint', '', new Text(0), 'APNS endpoint.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; + $provider = new Document([ + '$id' => $providerId, + 'name' => $name, + 'provider' => 'apns', + 'type' => 'push', + 'search' => $providerId . ' ' . $name . ' ' . 'apns' . ' ' . 'push', + 'default' => $default, + 'enabled' => $enabled, + 'credentials' => [ + 'authKey' => $authKey, + 'authKeyId' => $authKeyId, + 'teamId' => $teamId, + 'bundleId' => $bundleId, + 'endpoint' => $endpoint, + ], + ]); + + // Check if a default provider exists, if not, set this one as default + if ( + empty($dbForProject->findOne('providers', [ + Query::equal('default', [true]), + Query::equal('type', ['push']) + ])) + ) { + $provider->setAttribute('default', true); + } + + try { + $provider = $dbForProject->createDocument('providers', $provider); + } catch (DuplicateException) { + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($provider, Response::MODEL_PROVIDER); + }); + App::get('/v1/messaging/providers') ->desc('List Providers') ->groups(['api', 'messaging']) @@ -45,9 +580,8 @@ App::get('/v1/messaging/providers') if ($cursor) { $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('providers', [ + $cursorDocument = Authorization::skip(fn () => $dbForProject->findOne('providers', [ Query::equal('$id', [$providerId]), - Query::limit(1), ])); if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { @@ -88,74 +622,7 @@ App::get('/v1/messaging/providers/:id') $response->dynamic($provider, Response::MODEL_PROVIDER); }); -/** - * Email Providers - */ -App::post('/v1/messaging/providers/mailgun') - ->desc('Create Mailgun Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderMailgun') - ->label('sdk.description', '/docs/references/messaging/create-provider-mailgun.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('isEuRegion', false, new Boolean(), 'Set as EU region.', true) - ->param('from', '', new Text(256), 'Sender Email Address.') - ->param('apiKey', '', new Text(0), 'Mailgun API Key.') - ->param('domain', '', new Text(0), 'Mailgun Domain.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'mailgun', - 'type' => 'email', - 'default' => $default, - 'enabled' => $enabled, - 'search' => $providerId . ' ' . $name . ' ' . 'mailgun' . ' ' . 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - 'domain' => $domain, - 'isEuRegion' => $isEuRegion, - ], - 'options' => [ - 'from' => $from, - ] - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/mailgun') +App::patch('/v1/messaging/providers/mailgun/:id') ->desc('Update Mailgun Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -163,8 +630,8 @@ App::patch('/v1/messaging/providers/:id/mailgun') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderMailgun') - ->label('sdk.description', '/docs/references/messaging/update-provider-mailgun.md') + ->label('sdk.method', 'updateMailgunProvider') + ->label('sdk.description', '/docs/references/messaging/update-mailgun-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -194,15 +661,6 @@ App::patch('/v1/messaging/providers/:id/mailgun') $provider->setAttribute('search', $provider->getId() . ' ' . $name . ' ' . 'mailgun' . ' ' . 'email'); } - if ($isEuRegion === true || $isEuRegion === false) { - $credentials = $provider->getAttribute('credentials'); - $provider->setAttribute('credentials', [ - 'isEuRegion' => $isEuRegion, - 'apiKey' => $credentials['apiKey'], - 'domain' => $credentials['domain'], - ]); - } - if (!empty($from)) { $provider->setAttribute('options', [ 'from' => $from, @@ -213,83 +671,29 @@ App::patch('/v1/messaging/providers/:id/mailgun') $provider->setAttribute('enabled', $enabled); } - if ($apiKey || $domain) { - // Check if all credential variables are present - if ($apiKey && $domain) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'domain' => $domain, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if ($isEuRegion === true || $isEuRegion === false) { + $credentials['isEuRegion'] = $isEuRegion; } + if (!empty($apiKey)) { + $credentials['apiKey'] = $apiKey; + } + + if (!empty($domain)) { + $credentials['domain'] = $domain; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::post('/v1/messaging/providers/sendgrid') - ->desc('Create Sendgrid Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderSendgrid') - ->label('sdk.description', '/docs/references/messaging/create-provider-sendgrid.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('apiKey', '', new Text(0), 'Sendgrid API key.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'sendgrid', - 'type' => 'email', - 'default' => $default, - 'enabled' => $enabled, - 'options' => [], - 'search' => $providerId . ' ' . $name . ' ' . 'sendgrid' . ' ' . 'email', - 'credentials' => [ - 'apiKey' => $apiKey, - ], - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/sendgrid') +App::patch('/v1/messaging/providers/sendgrid/:id') ->desc('Update Sendgrid Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -297,8 +701,8 @@ App::patch('/v1/messaging/providers/:id/sendgrid') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderSendgrid') - ->label('sdk.description', '/docs/references/messaging/update-provider-sendgrid.md') + ->label('sdk.method', 'updateSendgridProvider') + ->label('sdk.description', '/docs/references/messaging/update-sendgrid-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -329,84 +733,19 @@ App::patch('/v1/messaging/providers/:id/sendgrid') $provider->setAttribute('enabled', $enabled); } - if ($apiKey) { + if (!empty($apiKey)) { $provider->setAttribute('credentials', [ 'apiKey' => $apiKey, ]); } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -/** - * SMS Providers - */ -App::post('/v1/messaging/providers/msg91') - ->desc('Create Msg91 Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderMsg91') - ->label('sdk.description', '/docs/references/messaging/create-provider-msg91.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('from', '', new Text(256), 'Sender Number.') - ->param('senderId', '', new Text(0), 'Msg91 Sender ID.') - ->param('authKey', '', new Text(0), 'Msg91 Auth Key.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $from, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'msg91', - 'type' => 'sms', - 'search' => $providerId . ' ' . $name . ' ' . 'msg91' . ' ' . 'sms', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'senderId' => $senderId, - 'authKey' => $authKey, - ], - 'options' => [ - 'from' => $from, - ] - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/msg91') +App::patch('/v1/messaging/providers/msg91/:id') ->desc('Update Msg91 Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -414,8 +753,8 @@ App::patch('/v1/messaging/providers/:id/msg91') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderMsg91') - ->label('sdk.description', '/docs/references/messaging/update-provider-msg91.md') + ->label('sdk.method', 'updateMsg91Provider') + ->label('sdk.description', '/docs/references/messaging/update-msg91-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -447,84 +786,25 @@ App::patch('/v1/messaging/providers/:id/msg91') $provider->setAttribute('enabled', $enabled); } - if ($senderId || $authKey) { - // Check if all credential variables are present - if ($senderId && $authKey) { - $provider->setAttribute('credentials', [ - 'senderId' => $senderId, - 'authKey' => $authKey, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if (!empty($senderId)) { + $credentials['senderId'] = $senderId; } + if (!empty($authKey)) { + $credentials['authKey'] = $authKey; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::post('/v1/messaging/providers/telesign') - ->desc('Create Telesign Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderTelesign') - ->label('sdk.description', '/docs/references/messaging/create-provider-telesign.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('username', '', new Text(0), 'Telesign username.') - ->param('password', '', new Text(0), 'Telesign password.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'telesign', - 'type' => 'sms', - 'search' => $providerId . ' ' . $name . ' ' . 'telesign' . ' ' . 'sms', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'username' => $username, - 'password' => $password, - ], - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/telesign') +App::patch('/v1/messaging/providers/telesign/:id') ->desc('Update Telesign Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -532,8 +812,8 @@ App::patch('/v1/messaging/providers/:id/telesign') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderTelesign') - ->label('sdk.description', '/docs/references/messaging/update-provider-telesign.md') + ->label('sdk.method', 'updateTelesignProvider') + ->label('sdk.description', '/docs/references/messaging/update-telesign-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -565,84 +845,25 @@ App::patch('/v1/messaging/providers/:id/telesign') $provider->setAttribute('enabled', $enabled); } - if ($username || $password) { - // Check if all credential variables are present - if ($username && $password) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'password' => $password, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if (!empty($username)) { + $credentials['username'] = $username; } + if (!empty($password)) { + $credentials['password'] = $password; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::post('/v1/messaging/providers/textmagic') - ->desc('Create Textmagic Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderTextmagic') - ->label('sdk.description', '/docs/references/messaging/create-provider-textmagic.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('username', '', new Text(0), 'Textmagic username.') - ->param('apiKey', '', new Text(0), 'Textmagic apiKey.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'text-magic', - 'type' => 'sms', - 'search' => $providerId . ' ' . $name . ' ' . 'text-magic' . ' ' . 'sms', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'username' => $username, - 'apiKey' => $apiKey, - ], - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/textmagic') +App::patch('/v1/messaging/providers/textmagic/:id') ->desc('Update Textmagic Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -650,8 +871,8 @@ App::patch('/v1/messaging/providers/:id/textmagic') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderTextmagic') - ->label('sdk.description', '/docs/references/messaging/update-provider-textmagic.md') + ->label('sdk.method', 'updateTextmagicProvider') + ->label('sdk.description', '/docs/references/messaging/update-textmagic-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -683,84 +904,25 @@ App::patch('/v1/messaging/providers/:id/textmagic') $provider->setAttribute('enabled', $enabled); } - if ($username || $apiKey) { - // Check if all credential variables are present - if ($username && $apiKey) { - $provider->setAttribute('credentials', [ - 'username' => $username, - 'apiKey' => $apiKey, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if (!empty($username)) { + $credentials['username'] = $username; } + if (!empty($apiKey)) { + $credentials['apiKey'] = $apiKey; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::post('/v1/messaging/providers/twilio') - ->desc('Create Twilio Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderTwilio') - ->label('sdk.description', '/docs/references/messaging/create-provider-twilio.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('accountSid', '', new Text(0), 'Twilio account secret ID.') - ->param('authToken', '', new Text(0), 'Twilio authentication token.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'twilio', - 'type' => 'sms', - 'search' => $providerId . ' ' . $name . ' ' . 'twilio' . ' ' . 'sms', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ], - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/twilio') +App::patch('/v1/messaging/providers/twilio/:id') ->desc('Update Twilio Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -768,8 +930,8 @@ App::patch('/v1/messaging/providers/:id/twilio') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderTwilio') - ->label('sdk.description', '/docs/references/messaging/update-provider-twilio.md') + ->label('sdk.method', 'updateTwilioProvider') + ->label('sdk.description', '/docs/references/messaging/update-twilio-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -801,84 +963,25 @@ App::patch('/v1/messaging/providers/:id/twilio') $provider->setAttribute('enabled', $enabled); } - if ($accountSid || $authToken) { - // Check if all credential variables are present - if ($accountSid && $authToken) { - $provider->setAttribute('credentials', [ - 'accountSid' => $accountSid, - 'authToken' => $authToken, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if (!empty($accountSid)) { + $credentials['accountSid'] = $accountSid; } + if (!empty($authToken)) { + $credentials['authToken'] = $authToken; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::post('/v1/messaging/providers/vonage') - ->desc('Create Vonage Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderVonage') - ->label('sdk.description', '/docs/references/messaging/create-provider-vonage.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('apiKey', '', new Text(0), 'Vonage API key.') - ->param('apiSecret', '', new Text(0), 'Vonage API secret.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'vonage', - 'type' => 'sms', - 'search' => $providerId . ' ' . $name . ' ' . 'vonage' . ' ' . 'sms', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ], - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/vonage') +App::patch('/v1/messaging/providers/vonage/:id') ->desc('Update Vonage Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -886,8 +989,8 @@ App::patch('/v1/messaging/providers/:id/vonage') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderVonage') - ->label('sdk.description', '/docs/references/messaging/update-provider-vonage.md') + ->label('sdk.method', 'updateVonageProvider') + ->label('sdk.description', '/docs/references/messaging/update-vonage-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -919,85 +1022,25 @@ App::patch('/v1/messaging/providers/:id/vonage') $provider->setAttribute('enabled', $enabled); } - if ($apiKey || $apiSecret) { - // Check if all credential variables are present - if ($apiKey && $apiSecret) { - $provider->setAttribute('credentials', [ - 'apiKey' => $apiKey, - 'apiSecret' => $apiSecret, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if (!empty($apiKey)) { + $credentials['apiKey'] = $apiKey; } + if (!empty($apiSecret)) { + $credentials['apiSecret'] = $apiSecret; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -/** - * Push Providers - */ -App::post('/v1/messaging/providers/fcm') - ->desc('Create FCM Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderFCM') - ->label('sdk.description', '/docs/references/messaging/create-provider-fcm.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('serverKey', '', new Text(0), 'FCM Server Key.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $serverKey, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'fcm', - 'type' => 'push', - 'search' => $providerId . ' ' . $name . ' ' . 'fcm' . ' ' . 'push', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'serverKey' => $serverKey, - ], - ]); - - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/fcm') +App::patch('/v1/messaging/providers/fcm/:id') ->desc('Update FCM Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -1005,8 +1048,8 @@ App::patch('/v1/messaging/providers/:id/fcm') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderFCM') - ->label('sdk.description', '/docs/references/messaging/update-provider-fcm.md') + ->label('sdk.method', 'updateFCMProvider') + ->label('sdk.description', '/docs/references/messaging/update-fcm-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -1037,81 +1080,18 @@ App::patch('/v1/messaging/providers/:id/fcm') $provider->setAttribute('enabled', $enabled); } - if ($serverKey) { + if (!empty($serverKey)) { $provider->setAttribute('credentials', ['serverKey' => $serverKey]); } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::post('/v1/messaging/providers/apns') - ->desc('Create APNS Provider') - ->groups(['api', 'messaging']) - ->label('audits.event', 'providers.create') - ->label('audits.resource', 'providers/{response.$id}') - ->label('scope', 'providers.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createProviderAPNS') - ->label('sdk.description', '/docs/references/messaging/create-provider-apns.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Provider name.') - ->param('default', false, new Boolean(), 'Set as default provider.', true) - ->param('enabled', true, new Boolean(), 'Set as enabled.', true) - ->param('authKey', '', new Text(0), 'APNS authentication key.') - ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.') - ->param('teamId', '', new Text(0), 'APNS team ID.') - ->param('bundleId', '', new Text(0), 'APNS bundle ID.') - ->param('endpoint', '', new Text(0), 'APNS endpoint.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $providerId, string $name, bool $default, bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; - $provider = new Document([ - '$id' => $providerId, - 'name' => $name, - 'provider' => 'apns', - 'type' => 'push', - 'search' => $providerId . ' ' . $name . ' ' . 'apns' . ' ' . 'push', - 'default' => $default, - 'enabled' => $enabled, - 'credentials' => [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ], - ]); - // Check if a default provider exists, if not, set this one as default - if ( - empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - ])) - ) { - $provider->setAttribute('default', true); - } - - try { - $provider = $dbForProject->createDocument('providers', $provider); - } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($provider, Response::MODEL_PROVIDER); - }); - -App::patch('/v1/messaging/providers/:id/apns') +App::patch('/v1/messaging/providers/apns/:id') ->desc('Update APNS Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -1119,8 +1099,8 @@ App::patch('/v1/messaging/providers/:id/apns') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateProviderAPNS') - ->label('sdk.description', '/docs/references/messaging/update-provider-apns.md') + ->label('sdk.method', 'updateAPNSProvider') + ->label('sdk.description', '/docs/references/messaging/update-apns-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) @@ -1155,24 +1135,31 @@ App::patch('/v1/messaging/providers/:id/apns') $provider->setAttribute('enabled', $enabled); } - if ($authKey || $authKeyId || $teamId || $bundleId || $endpoint) { - // Check if all credential variables are present - if ($authKey && $authKeyId && $teamId && $bundleId && $endpoint) { - $provider->setAttribute('credentials', [ - 'authKey' => $authKey, - 'authKeyId' => $authKeyId, - 'teamId' => $teamId, - 'bundleId' => $bundleId, - 'endpoint' => $endpoint, - ]); - } else { - // Not all credential params are present - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } + $credentials = $provider->getAttribute('credentials'); + + if (!empty($authKey)) { + $credentials['authKey'] = $authKey; } + if (!empty($authKeyId)) { + $credentials['authKeyId'] = $authKeyId; + } + + if (!empty($teamId)) { + $credentials['teamId'] = $teamId; + } + + if (!empty($bundleId)) { + $credentials['bundle'] = $bundleId; + } + + if (!empty($endpoint)) { + $credentials['endpoint'] = $endpoint; + } + + $provider->setAttribute('credentials', $credentials); + $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $response ->dynamic($provider, Response::MODEL_PROVIDER); @@ -1201,36 +1188,11 @@ App::delete('/v1/messaging/providers/:id') throw new Exception(Exception::PROVIDER_NOT_FOUND); } - $dbForProject->deleteCachedDocument('providers', $provider->getId()); $dbForProject->deleteDocument('providers', $provider->getId()); $response->noContent(); }); -App::get('/v1/messaging/messages/:id') - ->desc('Get Message') - ->groups(['api', 'messaging']) - ->label('scope', 'messages.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getMessage') - ->label('sdk.description', '/docs/references/messaging/get-message.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) - ->param('id', '', new UID(), 'Message ID.') - ->inject('dbForProject') - ->inject('response') - ->action(function (string $id, Database $dbForProject, Response $response) { - $message = $dbForProject->getDocument('messages', $id); - - if ($message->isEmpty()) { - throw new Exception(Exception::MESSAGE_NOT_FOUND); - } - - $response->dynamic($message, Response::MODEL_MESSAGE); - }); - App::post('/v1/messaging/messages/email') ->desc('Send an email.') ->groups(['api', 'messaging']) @@ -1245,12 +1207,12 @@ App::post('/v1/messaging/messages/email') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('providerId', '', new Text(128), 'Email Provider ID.') + ->param('providerId', '', new UID(), 'Email Provider ID.') ->param('to', [], new ArrayList(new Text(65535)), 'List of Topic IDs or List of User IDs or List of Target IDs.') - ->param('subject', '', new Text(128), 'Email Subject.') + ->param('subject', '', new Text(998), 'Email Subject.') ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(65407), 'Email Content.') - ->param('html', false, new Boolean(false), 'Is content of type HTML', true) + ->param('html', false, new Boolean(), 'Is content of type HTML', true) ->inject('dbForProject') ->inject('project') ->inject('messaging') @@ -1280,11 +1242,35 @@ App::post('/v1/messaging/messages/email') ])); $messaging - ->setMessageId($message->getId()) - ->setProject($project) - ->trigger(); + ->setMessageId($message->getId()) + ->setProject($project) + ->trigger(); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($message, Response::MODEL_MESSAGE); }); + +App::get('/v1/messaging/messages/:id') + ->desc('Get Message') + ->groups(['api', 'messaging']) + ->label('scope', 'messages.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'getMessage') + ->label('sdk.description', '/docs/references/messaging/get-message.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->param('id', '', new UID(), 'Message ID.') + ->inject('dbForProject') + ->inject('response') + ->action(function (string $id, Database $dbForProject, Response $response) { + $message = $dbForProject->getDocument('messages', $id); + + if ($message->isEmpty()) { + throw new Exception(Exception::MESSAGE_NOT_FOUND); + } + + $response->dynamic($message, Response::MODEL_MESSAGE); + }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 9b2dc516cb..244bc1150b 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1228,7 +1228,6 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - // Update the target identifier here $target->setAttribute('identifier', $identifier); $target = $dbForProject->updateDocument('targets', $target->getId(), $target); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index b5dc79917d..8e25a8210c 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -22,6 +22,9 @@ use Utopia\Messaging\Adapters\Email\SendGrid; use Utopia\Messaging\Messages\Email; use Utopia\Messaging\Messages\Push; use Utopia\Messaging\Messages\SMS; +use Appwrite\Extend\Exception; + +use function Swoole\Coroutine\batch; require_once __DIR__ . '/../init.php'; @@ -39,48 +42,9 @@ class MessagingV1 extends Worker public function getName(): string { - return "mails"; + return "messaging"; } - public function sms($record): ?SMSAdapter - { - $credentials = $record->getAttribute('credentials'); - return match ($record->getAttribute('provider')) { - 'mock' => new Mock('username', 'password'), - 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), - 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), - 'telesign' => new Telesign($credentials['username'], $credentials['password']), - 'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']), - 'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']), - default => null - }; - } - - public function push($record): ?PushAdapter - { - $credentials = $record->getAttribute('credentials'); - return match ($record->getAttribute('provider')) { - 'apns' => new APNS( - $credentials['authKey'], - $credentials['authKeyId'], - $credentials['teamId'], - $credentials['bundleId'], - $credentials['endpoint'] - ), - 'fcm' => new FCM($credentials['serverKey']), - default => null - }; - } - - public function email($record): ?EmailAdapter - { - $credentials = $record->getAttribute('credentials'); - return match ($record->getAttribute('provider')) { - 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']), - 'sendgrid' => new SendGrid($credentials['apiKey']), - default => null - }; - } public function init(): void { @@ -91,12 +55,11 @@ class MessagingV1 extends Worker $project = new Document($this->args['project']); $this->dbForProject = $this->getProjectDB($project); - $messageRecord = $this->dbForProject->getDocument('messages', $this->args['messageId']); + $message = $this->dbForProject->getDocument('messages', $this->args['messageId']); - $providerId = $messageRecord->getAttribute('providerId'); - $providerRecord = $this->dbForProject->getDocument('providers', $providerId); + $provider = $this->dbForProject->getDocument('providers', $message->getAttribute('providerId')); - $this->processMessage($messageRecord, $providerRecord); + $this->processMessage($message, $provider); } private function processMessage(Document $messageRecord, Document $providerRecord): void @@ -105,7 +68,7 @@ class MessagingV1 extends Worker 'sms' => $this->sms($providerRecord), 'push' => $this->push($providerRecord), 'email' => $this->email($providerRecord), - default => null + default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE) }; $recipientsId = $messageRecord->getAttribute('to'); @@ -115,7 +78,6 @@ class MessagingV1 extends Worker */ $recipients = []; - $topics = $this->dbForProject->find('topics', [Query::equal('$id', $recipientsId)]); foreach ($topics as $topic) { $recipients = \array_merge($recipients, $topic->getAttribute('targets')); @@ -128,6 +90,7 @@ class MessagingV1 extends Worker $targets = $this->dbForProject->find('targets', [Query::equal('$id', $recipientsId)]); $recipients = \array_merge($recipients, $targets); + $recipients = \array_filter($recipients, fn (Document $recipient) => $recipient->getAttribute('providerId') === $providerRecord->getId()); $identifiers = \array_map(function (Document $recipient) { return $recipient->getAttribute('identifier'); @@ -135,27 +98,42 @@ class MessagingV1 extends Worker $maxBatchSize = $provider->getMaxMessagesPerRequest(); $batches = \array_chunk($identifiers, $maxBatchSize); - $deliveredTo = 0; - foreach ($batches as $batch) { - $messageRecord->setAttribute('to', $batch); - $message = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->buildSMSMessage($messageRecord, $providerRecord), - 'push' => $this->buildPushMessage($messageRecord), - 'email' => $this->buildEmailMessage($messageRecord, $providerRecord), - default => null - }; - try { - $provider->send($message); - $deliveredTo += \count($batch); - } catch (Exception $e) { - $deliveryErrors = $messageRecord->getAttribute('deliveryErrors'); - foreach ($batch as $identifier) { - $deliveryErrors[] = 'Failed to send message to target' . $identifier . ': ' . $e->getMessage(); + $results = batch(\array_map(function ($batch) use ($messageRecord, $providerRecord, $provider) { + return function () use ($batch, $messageRecord, $providerRecord, $provider) { + $deliveredTo = 0; + $deliveryErrors = []; + $messageData = clone $messageRecord; + $messageData->setAttribute('to', $batch); + $message = match ($providerRecord->getAttribute('type')) { + 'sms' => $this->buildSMSMessage($messageRecord, $providerRecord), + 'push' => $this->buildPushMessage($messageRecord), + 'email' => $this->buildEmailMessage($messageRecord, $providerRecord), + default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE) + }; + try { + $provider->send($message); + $deliveredTo += \count($batch); + } catch (Exception $e) { + foreach ($batch as $identifier) { + $deliveryErrors[] = 'Failed to send message to target' . $identifier . ': ' . $e->getMessage(); + } + } finally { + return [ + 'deliveredTo' => $deliveredTo, + 'deliveryErrors' => $deliveryErrors, + ]; } - $messageRecord->setAttribute('deliveryErrors', $deliveryErrors); - } + }; + }, $batches)); + + $deliveredTo = 0; + $deliveryErrors = []; + foreach ($results as $result) { + $deliveredTo += $result['deliveredTo']; + $deliveryErrors = \array_merge($deliveryErrors, $result['deliveryErrors']); } + $messageRecord->setAttribute('deliveryErrors', $deliveryErrors); if (\count($messageRecord->getAttribute('deliveryErrors')) > 0) { $messageRecord->setAttribute('status', 'failed'); @@ -173,17 +151,58 @@ class MessagingV1 extends Worker { } - private function buildEmailMessage($message, $provider): Email + private function sms(Document $document): ?SMSAdapter + { + $credentials = $document->getAttribute('credentials'); + return match ($document->getAttribute('provider')) { + 'mock' => new Mock('username', 'password'), + 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), + 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), + 'telesign' => new Telesign($credentials['username'], $credentials['password']), + 'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']), + 'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']), + default => null + }; + } + + private function push(Document $document): ?PushAdapter + { + $credentials = $document->getAttribute('credentials'); + return match ($document->getAttribute('provider')) { + 'apns' => new APNS( + $credentials['authKey'], + $credentials['authKeyId'], + $credentials['teamId'], + $credentials['bundleId'], + $credentials['endpoint'] + ), + 'fcm' => new FCM($credentials['serverKey']), + default => null + }; + } + + private function email(Document $document): ?EmailAdapter + { + $credentials = $document->getAttribute('credentials'); + return match ($document->getAttribute('provider')) { + 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']), + 'sendgrid' => new SendGrid($credentials['apiKey']), + default => null + }; + } + + private function buildEmailMessage(Document $message, Document $provider): Email { $from = $provider['options']['from']; $to = $message['to']; $subject = $message['data']['subject']; $content = $message['data']['content']; $html = $message['data']['html']; - return new Email(to: $to, subject: $subject, content: $content, from: $from, html: $html); + + return new Email($to, $subject, $content, $from, null, $html); } - private function buildSMSMessage($message, $provider): SMS + private function buildSMSMessage(Document $message, Document $provider): SMS { $to = $message['to']; $content = $message['data']['content']; @@ -192,7 +211,7 @@ class MessagingV1 extends Worker return new SMS($to, $content, $from); } - private function buildPushMessage($message): Push + private function buildPushMessage(Document $message): Push { $to = $message['to']; $title = $message['data']['title']; @@ -204,6 +223,7 @@ class MessagingV1 extends Worker $color = $message['data']['color']; $tag = $message['data']['tag']; $badge = $message['data']['badge']; + return new Push($to, $title, $body, $data, $action, $sound, $icon, $color, $tag, $badge); } } diff --git a/composer.json b/composer.json index 3425c98419..efa0179f3b 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "utopia-php/image": "0.5.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.3.*", - "utopia-php/messaging": "dev-feat-push as 0.1.1", + "utopia-php/messaging": "0.2.*", "utopia-php/migration": "0.3.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.4.*", diff --git a/composer.lock b/composer.lock index e739e122c9..13040c831d 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": "6431be75373bf2e1bdbe2c638188d15f", + "content-hash": "237609b7e9fb20d807aa6e773bf72de6", "packages": [ { "name": "adhocore/jwt", @@ -1050,16 +1050,16 @@ }, { "name": "matomo/device-detector", - "version": "6.1.5", + "version": "6.1.6", "source": { "type": "git", "url": "https://github.com/matomo-org/device-detector.git", - "reference": "40ca2990dba2c1719e5c62168e822e0b86c167d4" + "reference": "5cbea85106e561c7138d03603eb6e05128480409" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/40ca2990dba2c1719e5c62168e822e0b86c167d4", - "reference": "40ca2990dba2c1719e5c62168e822e0b86c167d4", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/5cbea85106e561c7138d03603eb6e05128480409", + "reference": "5cbea85106e561c7138d03603eb6e05128480409", "shasum": "" }, "require": { @@ -1115,7 +1115,7 @@ "source": "https://github.com/matomo-org/matomo", "wiki": "https://dev.matomo.org/" }, - "time": "2023-08-17T16:17:41+00:00" + "time": "2023-10-02T10:01:54+00:00" }, { "name": "mongodb/mongodb", @@ -2152,16 +2152,16 @@ }, { "name": "utopia-php/database", - "version": "0.43.2", + "version": "0.43.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "f2626acd42665a9987c94af1c93bf20c28d55c9d" + "reference": "cabdd02e8dc1732eb0b22007c511e7bb3caa5c8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/f2626acd42665a9987c94af1c93bf20c28d55c9d", - "reference": "f2626acd42665a9987c94af1c93bf20c28d55c9d", + "url": "https://api.github.com/repos/utopia-php/database/zipball/cabdd02e8dc1732eb0b22007c511e7bb3caa5c8c", + "reference": "cabdd02e8dc1732eb0b22007c511e7bb3caa5c8c", "shasum": "" }, "require": { @@ -2202,9 +2202,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.43.2" + "source": "https://github.com/utopia-php/database/tree/0.43.4" }, - "time": "2023-09-07T19:04:33+00:00" + "time": "2023-09-28T09:00:05+00:00" }, { "name": "utopia-php/domains", @@ -2516,16 +2516,16 @@ }, { "name": "utopia-php/messaging", - "version": "dev-feat-push", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "2bb09220d0993a9f8f0afc63ff51382b13d93e18" + "reference": "2d0f474a106bb1da285f85e105c29b46085d3a43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/2bb09220d0993a9f8f0afc63ff51382b13d93e18", - "reference": "2bb09220d0993a9f8f0afc63ff51382b13d93e18", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/2d0f474a106bb1da285f85e105c29b46085d3a43", + "reference": "2d0f474a106bb1da285f85e105c29b46085d3a43", "shasum": "" }, "require": { @@ -2558,22 +2558,22 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/feat-push" + "source": "https://github.com/utopia-php/messaging/tree/0.2.0" }, - "time": "2023-09-14T20:29:49+00:00" + "time": "2023-09-14T20:48:42+00:00" }, { "name": "utopia-php/migration", - "version": "0.3.4", + "version": "0.3.5", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a" + "reference": "b2fd3a8310296f4e44ff0e85b0eb0230ad9a2f83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/ade836d61b3e1547bc9f0dc300ee75b24ab49f7a", - "reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/b2fd3a8310296f4e44ff0e85b0eb0230ad9a2f83", + "reference": "b2fd3a8310296f4e44ff0e85b0eb0230ad9a2f83", "shasum": "" }, "require": { @@ -2596,16 +2596,6 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Eldad Fux", - "email": "eldad@appwrite.io" - }, - { - "name": "Bradley Schofield", - "email": "bradley@appwrite.io" - } - ], "description": "A simple library to migrate resources between services.", "keywords": [ "framework", @@ -2616,9 +2606,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.3.4" + "source": "https://github.com/utopia-php/migration/tree/0.3.5" }, - "time": "2023-09-14T17:17:55+00:00" + "time": "2023-09-25T16:51:47+00:00" }, { "name": "utopia-php/mongo", @@ -3442,16 +3432,16 @@ }, { "name": "doctrine/deprecations", - "version": "v1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", "shasum": "" }, "require": { @@ -3483,9 +3473,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + "source": "https://github.com/doctrine/deprecations/tree/1.1.2" }, - "time": "2023-06-03T09:27:29+00:00" + "time": "2023-09-27T20:04:15+00:00" }, { "name": "doctrine/instantiator", @@ -4145,16 +4135,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.1", + "version": "1.24.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01" + "reference": "bcad8d995980440892759db0c32acae7c8e79442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", - "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442", + "reference": "bcad8d995980440892759db0c32acae7c8e79442", "shasum": "" }, "require": { @@ -4186,9 +4176,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2" }, - "time": "2023-09-18T12:18:02+00:00" + "time": "2023-09-26T12:28:12+00:00" }, { "name": "phpunit/php-code-coverage", @@ -6001,18 +5991,9 @@ "time": "2023-08-28T11:09:02+00:00" } ], - "aliases": [ - { - "package": "utopia-php/messaging", - "version": "dev-feat-push", - "alias": "0.1.1", - "alias_normalized": "0.1.1.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/messaging": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index 1df75dfedf..cbfb7981ac 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -15,7 +15,6 @@ class Messaging extends Event } - /** * Sets message ID for the messaging event. * diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 96f2b12308..7f4cb84b05 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -748,7 +748,7 @@ class AccountCustomClientTest extends Scope $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - if ($to === '' || $from === '' || $authKey === '' || $senderId === '') { + if (empty($to) || empty($from) || empty($authKey) || empty($senderId)) { $this->markTestSkipped('SMS provider not configured'); } @@ -758,10 +758,8 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Sms provider', - 'provider' => 'msg91', - 'type' => 'sms', 'senderId' => $senderId, 'authKey' => $authKey, 'default' => true, @@ -1032,7 +1030,7 @@ class AccountCustomClientTest extends Scope $this->assertEmpty($response['body']['secret']); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); - \sleep(2); + \sleep(3); $message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $response['body']['$id'], [ 'origin' => 'http://localhost', diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 5970883dbe..dc399cf2b3 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -128,7 +128,7 @@ class AccountTest extends Scope $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - if ($to === '' || $from === '' || $authKey === '' || $senderId === '') { + if (empty($to) || empty($from) || empty($authKey) || empty($senderId)) { $this->markTestSkipped('SMS provider not configured'); } @@ -137,10 +137,8 @@ class AccountTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Sms Provider', - 'provider' => 'msg91', - 'type' => 'sms', 'from' => $from, 'senderId' => $senderId, 'authKey' => $authKey, diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index bbc8b56693..05092fdd2e 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -137,7 +137,7 @@ trait MessagingBase ], ]; foreach (\array_keys($providersParams) as $index => $key) { - $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $providers[$index]['$id'] . '/' . $key, [ + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $key . '/' . $providers[$index]['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -147,7 +147,7 @@ trait MessagingBase $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); } - $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/' . $providers[1]['$id'] . '/mailgun', [ + $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/mailgun/' . $providers[1]['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], From 61785ab35a25d7ccec44f67836a259b4e61635a7 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 4 Oct 2023 16:19:05 +0530 Subject: [PATCH 62/72] typo fix --- app/controllers/api/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index f2a61cde36..3fc88791c2 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -476,7 +476,7 @@ App::post('/v1/messaging/providers/fcm') if ( empty($dbForProject->findOne('providers', [ Query::equal('default', [true]), - Query::equal('type', ['pushq']) + Query::equal('type', ['push']) ])) ) { $provider->setAttribute('default', true); From c9c49158a3acaa130ef21c7328999bd3aefe74a6 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 4 Oct 2023 16:24:29 +0530 Subject: [PATCH 63/72] changes to validator length --- app/controllers/api/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 3fc88791c2..d9b5543e5c 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1208,7 +1208,7 @@ App::post('/v1/messaging/messages/email') ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('providerId', '', new UID(), 'Email Provider ID.') - ->param('to', [], new ArrayList(new Text(65535)), 'List of Topic IDs or List of User IDs or List of Target IDs.') + ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(998), 'Email Subject.') ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(65407), 'Email Content.') From abab68f1a14c55ae3b8643bd5de46a07186a4659 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 4 Oct 2023 17:28:38 +0530 Subject: [PATCH 64/72] fixes catching in messaging worker --- app/workers/messaging.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 8e25a8210c..1a1a4fad4b 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -106,15 +106,15 @@ class MessagingV1 extends Worker $messageData = clone $messageRecord; $messageData->setAttribute('to', $batch); $message = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->buildSMSMessage($messageRecord, $providerRecord), - 'push' => $this->buildPushMessage($messageRecord), - 'email' => $this->buildEmailMessage($messageRecord, $providerRecord), + 'sms' => $this->buildSMSMessage($messageData, $providerRecord), + 'push' => $this->buildPushMessage($messageData), + 'email' => $this->buildEmailMessage($messageData, $providerRecord), default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE) }; try { $provider->send($message); $deliveredTo += \count($batch); - } catch (Exception $e) { + } catch (\Exception $e) { foreach ($batch as $identifier) { $deliveryErrors[] = 'Failed to send message to target' . $identifier . ': ' . $e->getMessage(); } From 80a19f9862536b3d4a3b4fa8c7ded7895888ef70 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Wed, 4 Oct 2023 17:30:40 +0530 Subject: [PATCH 65/72] unique to ID::unique --- .../e2e/Services/Messaging/MessagingBase.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 05092fdd2e..e9225b93d6 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -3,6 +3,7 @@ namespace Tests\E2E\Services\Messaging; use Tests\E2E\Client; +use Utopia\Database\Helpers\ID; trait MessagingBase { @@ -10,55 +11,55 @@ trait MessagingBase { $providersParams = [ 'sendgrid' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Sengrid1', 'apiKey' => 'my-apikey', ], 'mailgun' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Mailgun1', 'apiKey' => 'my-apikey', 'domain' => 'my-domain', 'from' => 'sender-email@my-domain', ], 'twilio' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Twilio1', 'accountSid' => 'my-accountSid', 'authToken' => 'my-authToken', ], 'telesign' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Telesign1', 'username' => 'my-username', 'password' => 'my-password', ], 'textmagic' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Textmagic1', 'username' => 'my-username', 'apiKey' => 'my-apikey', ], 'msg91' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Ms91-1', 'senderId' => 'my-senderid', 'authKey' => 'my-authkey', 'from' => '+123456789' ], 'vonage' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'Vonage1', 'apiKey' => 'my-apikey', 'apiSecret' => 'my-apisecret', ], 'fcm' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'FCM1', 'serverKey' => 'my-serverkey', ], 'apns' => [ - 'providerId' => 'unique()', + 'providerId' => ID::unique(), 'name' => 'APNS1', 'authKey' => 'my-authkey', 'authKeyId' => 'my-authkeyid', From fb98d21ae5f7fc64bbea70b570e895556c2df0ea Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 5 Oct 2023 02:12:04 +0530 Subject: [PATCH 66/72] adds graphql test cases for provider endpoints --- app/controllers/api/messaging.php | 8 +- tests/e2e/Services/GraphQL/AccountTest.php | 2 +- tests/e2e/Services/GraphQL/Base.php | 281 ++++++++++++++++-- tests/e2e/Services/GraphQL/MessagingTest.php | 260 ++++++++++++++++ .../e2e/Services/Messaging/MessagingBase.php | 6 +- 5 files changed, 520 insertions(+), 37 deletions(-) create mode 100644 tests/e2e/Services/GraphQL/MessagingTest.php diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index d9b5543e5c..396d81c06b 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -445,7 +445,7 @@ App::post('/v1/messaging/providers/fcm') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createFCMProvider') + ->label('sdk.method', 'createFcmProvider') ->label('sdk.description', '/docs/references/messaging/create-fcm-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) @@ -501,7 +501,7 @@ App::post('/v1/messaging/providers/apns') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createAPNSProvider') + ->label('sdk.method', 'createApnsProvider') ->label('sdk.description', '/docs/references/messaging/create-apns-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) @@ -1048,7 +1048,7 @@ App::patch('/v1/messaging/providers/fcm/:id') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateFCMProvider') + ->label('sdk.method', 'updateFcmProvider') ->label('sdk.description', '/docs/references/messaging/update-fcm-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) @@ -1099,7 +1099,7 @@ App::patch('/v1/messaging/providers/apns/:id') ->label('scope', 'providers.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateAPNSProvider') + ->label('sdk.method', 'updateApnsProvider') ->label('sdk.description', '/docs/references/messaging/update-apns-provider.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index dc399cf2b3..801be808c9 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -133,7 +133,7 @@ class AccountTest extends Scope } $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_PROVIDER); + $query = $this->getQuery(self::$CREATE_MSG91_PROVIDER); $graphQLPayload = [ 'query' => $query, 'variables' => [ diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index c670f8e17c..3a7859662a 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -197,6 +197,29 @@ trait Base public static string $GET_QRCODE = 'get_qrcode'; public static string $GET_USER_INITIALS = 'get_user_initials'; + // Providers + public static string $CREATE_MAILGUN_PROVIDER = 'create_mailgun_provider'; + public static string $CREATE_SENDGRID_PROVIDER = 'create_sendgrid_provider'; + public static string $CREATE_TWILIO_PROVIDER = 'create_twilio_provider'; + public static string $CREATE_TELESIGN_PROVIDER = 'create_telesign_provider'; + public static string $CREATE_TEXTMAGIC_PROVIDER = 'create_textmagic_provider'; + public static string $CREATE_MSG91_PROVIDER = 'create_msg91_provider'; + public static string $CREATE_VONAGE_PROVIDER = 'create_vonage_provider'; + public static string $CREATE_FCM_PROVIDER = 'create_fcm_provider'; + public static string $CREATE_APNS_PROVIDER = 'create_apns_provider'; + public static string $LIST_PROVIDERS = 'list_providers'; + public static string $GET_PROVIDER = 'get_provider'; + public static string $UPDATE_MAILGUN_PROVIDER = 'update_mailgun_provider'; + public static string $UPDATE_SENDGRID_PROVIDER = 'update_sendgrid_provider'; + public static string $UPDATE_TWILIO_PROVIDER = 'update_twilio_provider'; + public static string $UPDATE_TELESIGN_PROVIDER = 'update_telesign_provider'; + public static string $UPDATE_TEXTMAGIC_PROVIDER = 'update_textmagic_provider'; + public static string $UPDATE_MSG91_PROVIDER = 'update_msg91_provider'; + public static string $UPDATE_VONAGE_PROVIDER = 'update_vonage_provider'; + public static string $UPDATE_FCM_PROVIDER = 'update_fcm_provider'; + public static string $UPDATE_APNS_PROVIDER = 'update_apns_provider'; + public static string $DELETE_PROVIDER = 'delete_provider'; + // Complex queries public static string $COMPLEX_QUERY = 'complex_query'; @@ -296,8 +319,6 @@ trait Base } '; - public static string $CREATE_PROVIDER = 'create_provider'; - public function getQuery(string $name): string { switch ($name) { @@ -1688,6 +1709,235 @@ trait Base status } }'; + case self::$CREATE_MAILGUN_PROVIDER: + return 'mutation createMailgunProvider($providerId: String!, $name: String!, $domain: String!, $apiKey: String!, $from: String!) { + messagingCreateMailgunProvider(providerId: $providerId, name: $name, domain: $domain, apiKey: $apiKey, from: $from) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_SENDGRID_PROVIDER: + return 'mutation createSendgridProvider($providerId: String!, $name: String!, $apiKey: String!) { + messagingCreateSendgridProvider(providerId: $providerId, name: $name, apiKey: $apiKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_TWILIO_PROVIDER: + return 'mutation createTwilioProvider($providerId: String!, $name: String!, $accountSid: String!, $authToken: String!) { + messagingCreateTwilioProvider(providerId: $providerId, name: $name, accountSid: $accountSid, authToken: $authToken) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_TELESIGN_PROVIDER: + return 'mutation createTelesignProvider($providerId: String!, $name: String!, $username: String!, $password: String!) { + messagingCreateTelesignProvider(providerId: $providerId, name: $name, username: $username, password: $password) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_TEXTMAGIC_PROVIDER: + return 'mutation createTextmagicProvider($providerId: String!, $name: String!, $username: String!, $apiKey: String!) { + messagingCreateTextmagicProvider(providerId: $providerId, name: $name, username: $username, apiKey: $apiKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_MSG91_PROVIDER: + return 'mutation createMsg91Provider($providerId: String!, $name: String!, $from: String!, $senderId: String!, $authKey: String!, $default: Boolean, $enabled: Boolean) { + messagingCreateMsg91Provider(providerId: $providerId, name: $name, from: $from, senderId: $senderId, authKey: $authKey, default: $default, enabled: $enabled) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_VONAGE_PROVIDER: + return 'mutation createVonageProvider($providerId: String!, $name: String!, $apiKey: String!, $apiSecret: String!) { + messagingCreateVonageProvider(providerId: $providerId, name: $name, apiKey: $apiKey, apiSecret: $apiSecret) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_FCM_PROVIDER: + return 'mutation createFcmProvider($providerId: String!, $name: String!, $serverKey: String!) { + messagingCreateFcmProvider(providerId: $providerId, name: $name, serverKey: $serverKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$CREATE_APNS_PROVIDER: + return 'mutation createApnsProvider($providerId: String!, $name: String!, $authKey: String!, $authKeyId: String!, $teamId: String!, $bundleId: String!, $endpoint: String!) { + messagingCreateApnsProvider(providerId: $providerId, name: $name, authKey: $authKey, authKeyId: $authKeyId, teamId: $teamId, bundleId: $bundleId, endpoint: $endpoint) { + _id + name + provider + type + default + enabled + } + }'; + case self::$LIST_PROVIDERS: + return 'query listProviders { + messagingListProviders { + total + providers { + _id + name + provider + type + default + enabled + } + } + }'; + case self::$GET_PROVIDER: + return 'query getProvider($id: String!) { + messagingGetProvider(id: $id) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_MAILGUN_PROVIDER: + return 'mutation updateMailgunProvider($id: String!, $name: String!, $domain: String!, $apiKey: String!, $isEuRegion: Boolean, $enabled: Boolean) { + messagingUpdateMailgunProvider(id: $id, name: $name, domain: $domain, apiKey: $apiKey, isEuRegion: $isEuRegion, enabled: $enabled) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_SENDGRID_PROVIDER: + return 'mutation messagingUpdateSendgridProvider($id: String!, $name: String!, $apiKey: String!) { + messagingUpdateSendgridProvider(id: $id, name: $name, apiKey: $apiKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_TWILIO_PROVIDER: + return 'mutation updateTwilioProvider($id: String!, $name: String!, $accountSid: String!, $authToken: String!) { + messagingUpdateTwilioProvider(id: $id, name: $name, accountSid: $accountSid, authToken: $authToken) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_TELESIGN_PROVIDER: + return 'mutation updateTelesignProvider($id: String!, $name: String!, $username: String!, $password: String!) { + messagingUpdateTelesignProvider(id: $id, name: $name, username: $username, password: $password) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_TEXTMAGIC_PROVIDER: + return 'mutation updateTextmagicProvider($id: String!, $name: String!, $username: String!, $apiKey: String!) { + messagingUpdateTextmagicProvider(id: $id, name: $name, username: $username, apiKey: $apiKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_MSG91_PROVIDER: + return 'mutation updateMsg91Provider($id: String!, $name: String!, $senderId: String!, $authKey: String!) { + messagingUpdateMsg91Provider(id: $id, name: $name, senderId: $senderId, authKey: $authKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_VONAGE_PROVIDER: + return 'mutation updateVonageProvider($id: String!, $name: String!, $apiKey: String!, $apiSecret: String!) { + messagingUpdateVonageProvider(id: $id, name: $name, apiKey: $apiKey, apiSecret: $apiSecret) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_FCM_PROVIDER: + return 'mutation updateFcmProvider($id: String!, $name: String!, $serverKey: String!) { + messagingUpdateFcmProvider(id: $id, name: $name, serverKey: $serverKey) { + _id + name + provider + type + default + enabled + } + }'; + case self::$UPDATE_APNS_PROVIDER: + return 'mutation updateApnsProvider($id: String!, $name: String!, $authKey: String!, $authKeyId: String!, $teamId: String!, $bundleId: String!, $endpoint: String!) { + messagingUpdateApnsProvider(id: $id, name: $name, authKey: $authKey, authKeyId: $authKeyId, teamId: $teamId, bundleId: $bundleId, endpoint: $endpoint) { + _id + name + provider + type + default + enabled + } + }'; + case self::$DELETE_PROVIDER: + return 'mutation deleteProvider($id: String!) { + messagingDeleteProvider(id: $id) { + status + } + }'; case self::$COMPLEX_QUERY: return 'mutation complex($databaseId: String!, $databaseName: String!, $collectionId: String!, $collectionName: String!, $documentSecurity: Boolean!, $collectionPermissions: [String!]!) { databasesCreate(databaseId: $databaseId, name: $databaseName) { @@ -1931,33 +2181,6 @@ trait Base } } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; - case self::$CREATE_PROVIDER: - return 'mutation createProviderMsg91( - $providerId: String!, - $name: String!, - $from: String!, - $senderId: String!, - $authKey: String! - $default: Boolean, - $enabled: Boolean, - ) { - messagingCreateProviderMsg91( - providerId: $providerId, - name: $name, - from: $from, - senderId: $senderId, - authKey: $authKey - default: $default, - enabled: $enabled, - ) { - _id - name - provider - type - default - enabled - } - }'; } throw new \InvalidArgumentException('Invalid query type'); diff --git a/tests/e2e/Services/GraphQL/MessagingTest.php b/tests/e2e/Services/GraphQL/MessagingTest.php new file mode 100644 index 0000000000..1bc5e70477 --- /dev/null +++ b/tests/e2e/Services/GraphQL/MessagingTest.php @@ -0,0 +1,260 @@ + [ + 'providerId' => ID::unique(), + 'name' => 'Sengrid1', + 'apiKey' => 'my-apikey', + ], + 'Mailgun' => [ + 'providerId' => ID::unique(), + 'name' => 'Mailgun1', + 'apiKey' => 'my-apikey', + 'domain' => 'my-domain', + 'from' => 'sender-email@my-domain', + ], + 'Twilio' => [ + 'providerId' => ID::unique(), + 'name' => 'Twilio1', + 'accountSid' => 'my-accountSid', + 'authToken' => 'my-authToken', + ], + 'Telesign' => [ + 'providerId' => ID::unique(), + 'name' => 'Telesign1', + 'username' => 'my-username', + 'password' => 'my-password', + ], + 'Textmagic' => [ + 'providerId' => ID::unique(), + 'name' => 'Textmagic1', + 'username' => 'my-username', + 'apiKey' => 'my-apikey', + ], + 'Msg91' => [ + 'providerId' => ID::unique(), + 'name' => 'Ms91-1', + 'senderId' => 'my-senderid', + 'authKey' => 'my-authkey', + 'from' => '+123456789' + ], + 'Vonage' => [ + 'providerId' => ID::unique(), + 'name' => 'Vonage1', + 'apiKey' => 'my-apikey', + 'apiSecret' => 'my-apisecret', + ], + 'Fcm' => [ + 'providerId' => ID::unique(), + 'name' => 'FCM1', + 'serverKey' => 'my-serverkey', + ], + 'Apns' => [ + 'providerId' => ID::unique(), + 'name' => 'APNS1', + 'authKey' => 'my-authkey', + 'authKeyId' => 'my-authkeyid', + 'teamId' => 'my-teamid', + 'bundleId' => 'my-bundleid', + 'endpoint' => 'my-endpoint', + ], + ]; + + $providers = []; + + foreach (\array_keys($providersParams) as $key) { + $query = $this->getQuery('create_' . \strtolower($key) . '_provider'); + $graphQLPayload = [ + 'query' => $query, + 'variables' => $providersParams[$key], + ]; + $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), $graphQLPayload); + \array_push($providers, $response['body']['data']['messagingCreate' . $key . 'Provider']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($providersParams[$key]['name'], $response['body']['data']['messagingCreate' . $key . 'Provider']['name']); + } + + return $providers; + } + + /** + * @depends testCreateProviders + */ + public function testUpdateProviders(array $providers): array + { + $providersParams = [ + 'Sendgrid' => [ + 'id' => $providers[0]['_id'], + 'name' => 'Sengrid2', + 'apiKey' => 'my-apikey', + ], + 'Mailgun' => [ + 'id' => $providers[1]['_id'], + 'name' => 'Mailgun2', + 'apiKey' => 'my-apikey', + 'domain' => 'my-domain', + ], + 'Twilio' => [ + 'id' => $providers[2]['_id'], + 'name' => 'Twilio2', + 'accountSid' => 'my-accountSid', + 'authToken' => 'my-authToken', + ], + 'Telesign' => [ + 'id' => $providers[3]['_id'], + 'name' => 'Telesign2', + 'username' => 'my-username', + 'password' => 'my-password', + ], + 'Textmagic' => [ + 'id' => $providers[4]['_id'], + 'name' => 'Textmagic2', + 'username' => 'my-username', + 'apiKey' => 'my-apikey', + ], + 'Msg91' => [ + 'id' => $providers[5]['_id'], + 'name' => 'Ms91-2', + 'senderId' => 'my-senderid', + 'authKey' => 'my-authkey', + ], + 'Vonage' => [ + 'id' => $providers[6]['_id'], + 'name' => 'Vonage2', + 'apiKey' => 'my-apikey', + 'apiSecret' => 'my-apisecret', + ], + 'Fcm' => [ + 'id' => $providers[7]['_id'], + 'name' => 'FCM2', + 'serverKey' => 'my-serverkey', + ], + 'Apns' => [ + 'id' => $providers[8]['_id'], + 'name' => 'APNS2', + 'authKey' => 'my-authkey', + 'authKeyId' => 'my-authkeyid', + 'teamId' => 'my-teamid', + 'bundleId' => 'my-bundleid', + 'endpoint' => 'my-endpoint', + ], + ]; + foreach (\array_keys($providersParams) as $index => $key) { + $query = $this->getQuery('update_' . \strtolower($key) . '_provider'); + $graphQLPayload = [ + 'query' => $query, + 'variables' => $providersParams[$key], + ]; + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $graphQLPayload); + $providers[$index] = $response['body']['data']['messagingUpdate' . $key . 'Provider']; + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($providersParams[$key]['name'], $response['body']['data']['messagingUpdate' . $key . 'Provider']['name']); + } + + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'query' => $this->getQuery('update_mailgun_provider'), + 'variables' => [ + 'id' => $providers[1]['_id'], + 'name' => 'Mailgun2', + 'apiKey' => 'my-apikey', + 'domain' => 'my-domain', + 'isEuRegion' => true, + 'enabled' => false, + ] + ]); + $providers[1] = $response['body']['data']['messagingUpdateMailgunProvider']; + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Mailgun2', $response['body']['data']['messagingUpdateMailgunProvider']['name']); + $this->assertEquals(false, $response['body']['data']['messagingUpdateMailgunProvider']['enabled']); + return $providers; + } + + /** + * @depends testUpdateProviders + */ + public function testListProviders(array $providers) + { + $query = $this->getQuery(self::$LIST_PROVIDERS); + $graphQLPayload = [ + 'query' => $query, + ]; + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $graphQLPayload); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(\count($providers), \count($response['body']['data']['messagingListProviders']['providers'])); + } + + /** + * @depends testUpdateProviders + */ + public function testGetProvider(array $providers) + { + $query = $this->getQuery(self::$GET_PROVIDER); + $graphQLPayload = [ + 'query' => $query, + 'variables' => [ + 'id' => $providers[0]['_id'], + ] + ]; + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $graphQLPayload); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($providers[0]['name'], $response['body']['data']['messagingGetProvider']['name']); + } + + /** + * @depends testUpdateProviders + */ + public function testDeleteProvider(array $providers) + { + foreach ($providers as $provider) { + $query = $this->getQuery(self::$DELETE_PROVIDER); + $graphQLPayload = [ + 'query' => $query, + 'variables' => [ + 'id' => $provider['_id'], + ] + ]; + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $graphQLPayload); + $this->assertEquals(204, $response['headers']['status-code']); + } + } +} diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index e9225b93d6..3282330d86 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -76,9 +76,9 @@ trait MessagingBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), $providersParams[$key]); - \array_push($providers, $response['body']); $this->assertEquals(201, $response['headers']['status-code']); $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); + \array_push($providers, $response['body']); } return $providers; @@ -143,9 +143,9 @@ trait MessagingBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], $providersParams[$key]); - $providers[$index] = $response['body']; $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); + $providers[$index] = $response['body']; } $response = $this->client->call(Client::METHOD_PATCH, '/messaging/providers/mailgun/' . $providers[1]['$id'], [ @@ -159,10 +159,10 @@ trait MessagingBase 'isEuRegion' => true, 'enabled' => false, ]); - $providers[1] = $response['body']; $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('Mailgun2', $response['body']['name']); $this->assertEquals(false, $response['body']['enabled']); + $providers[1] = $response['body']; return $providers; } From c5408393c8763d314e73e12c738862da08465b04 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:26:02 -0700 Subject: [PATCH 67/72] Update logo in README-CN.md --- README-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-CN.md b/README-CN.md index 0e55f07ba1..1ba84705b1 100644 --- a/README-CN.md +++ b/README-CN.md @@ -2,7 +2,7 @@

- Appwrite Logo + Appwrite Logo

适用于[Flutter/Vue/Angular/React/iOS/Android/* 等等平台 *]的完整后端服务 From 22d445587ebd77cafbf5912642b58bedbfb0ad7e Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 5 Oct 2023 16:57:48 +0530 Subject: [PATCH 68/72] review changes --- app/controllers/api/account.php | 17 +++++--- app/controllers/api/messaging.php | 71 ++++++++++++++++--------------- app/controllers/api/users.php | 7 +-- app/workers/messaging.php | 4 +- src/Appwrite/Event/Messaging.php | 1 - 5 files changed, 52 insertions(+), 48 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 228a0621cd..23d8aea1cc 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1355,9 +1355,9 @@ App::post('/v1/account/sessions/phone') ])); $messaging - ->setMessageId($messageDoc->getId()) - ->setProject($project) - ->trigger(); + ->setMessageId($messageDoc->getId()) + ->setProject($project) + ->trigger(); $events->setPayload( $response->output( @@ -2964,7 +2964,10 @@ App::post('/v1/account/verification/phone') $message = $message->setParam('{{token}}', $secret); $message = $message->render(); - $target = $dbForProject->findOne('targets', [Query::equal('identifier', [$user->getAttribute('phone')]), Query::equal('providerInternalId', [$provider->getInternalId()])]); + $target = $dbForProject->findOne('targets', [ + Query::equal('identifier', [$user->getAttribute('phone')]), + Query::equal('providerInternalId', [$provider->getInternalId()]) + ]); if (!$target) { $target = $dbForProject->createDocument('targets', new Document([ @@ -2987,9 +2990,9 @@ App::post('/v1/account/verification/phone') ])); $messaging - ->setMessageId($messageDoc->getId()) - ->setProject($project) - ->trigger(); + ->setMessageId($messageDoc->getId()) + ->setProject($project) + ->trigger(); $events ->setParam('userId', $user->getId()) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 396d81c06b..cc1df6ab62 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -69,8 +69,8 @@ App::post('/v1/messaging/providers/mailgun') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['email']) + Query::equal('default', [true]), + Query::equal('type', ['email']) ])) ) { $provider->setAttribute('default', true); @@ -79,7 +79,7 @@ App::post('/v1/messaging/providers/mailgun') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -126,8 +126,8 @@ App::post('/v1/messaging/providers/sendgrid') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['sms']) + Query::equal('default', [true]), + Query::equal('type', ['sms']) ])) ) { $provider->setAttribute('default', true); @@ -136,7 +136,7 @@ App::post('/v1/messaging/providers/sendgrid') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -198,13 +198,14 @@ App::post('/v1/messaging/providers/msg91') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($provider, Response::MODEL_PROVIDER); }); + App::post('/v1/messaging/providers/telesign') ->desc('Create Telesign Provider') ->groups(['api', 'messaging']) @@ -245,8 +246,8 @@ App::post('/v1/messaging/providers/telesign') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['sms']) + Query::equal('default', [true]), + Query::equal('type', ['sms']) ])) ) { $provider->setAttribute('default', true); @@ -255,7 +256,7 @@ App::post('/v1/messaging/providers/telesign') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -303,8 +304,8 @@ App::post('/v1/messaging/providers/textmagic') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['sms']) + Query::equal('default', [true]), + Query::equal('type', ['sms']) ])) ) { $provider->setAttribute('default', true); @@ -313,7 +314,7 @@ App::post('/v1/messaging/providers/textmagic') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -361,8 +362,8 @@ App::post('/v1/messaging/providers/twilio') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['sms']) + Query::equal('default', [true]), + Query::equal('type', ['sms']) ])) ) { $provider->setAttribute('default', true); @@ -371,7 +372,7 @@ App::post('/v1/messaging/providers/twilio') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -419,7 +420,7 @@ App::post('/v1/messaging/providers/vonage') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('default', [true]), Query::equal('type', ['sms']) ])) ) { @@ -429,7 +430,7 @@ App::post('/v1/messaging/providers/vonage') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -475,8 +476,8 @@ App::post('/v1/messaging/providers/fcm') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['push']) + Query::equal('default', [true]), + Query::equal('type', ['push']) ])) ) { $provider->setAttribute('default', true); @@ -485,7 +486,7 @@ App::post('/v1/messaging/providers/fcm') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -539,8 +540,8 @@ App::post('/v1/messaging/providers/apns') // Check if a default provider exists, if not, set this one as default if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), - Query::equal('type', ['push']) + Query::equal('default', [true]), + Query::equal('type', ['push']) ])) ) { $provider->setAttribute('default', true); @@ -549,7 +550,7 @@ App::post('/v1/messaging/providers/apns') try { $provider = $dbForProject->createDocument('providers', $provider); } catch (DuplicateException) { - throw new Exception(Exception::PROVIDER_ALREADY_EXISTS, 'Provider already exists.'); + throw new Exception(Exception::PROVIDER_ALREADY_EXISTS); } $response @@ -584,7 +585,7 @@ App::get('/v1/messaging/providers') Query::equal('$id', [$providerId]), ])); - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + if ($cursorDocument === false || $cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); } @@ -653,7 +654,7 @@ App::patch('/v1/messaging/providers/mailgun/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'mailgun') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -721,7 +722,7 @@ App::patch('/v1/messaging/providers/sendgrid/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'sendgrid') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -774,7 +775,7 @@ App::patch('/v1/messaging/providers/msg91/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'msg91') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -833,7 +834,7 @@ App::patch('/v1/messaging/providers/telesign/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'telesign') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -892,7 +893,7 @@ App::patch('/v1/messaging/providers/textmagic/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'text-magic') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -951,7 +952,7 @@ App::patch('/v1/messaging/providers/twilio/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'twilio') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -1010,7 +1011,7 @@ App::patch('/v1/messaging/providers/vonage/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'vonage') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -1068,7 +1069,7 @@ App::patch('/v1/messaging/providers/fcm/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'fcm') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -1123,7 +1124,7 @@ App::patch('/v1/messaging/providers/apns/:id') $providerAttr = $provider->getAttribute('provider'); if ($providerAttr !== 'apns') { - throw new Exception(Exception::PROVIDER_INCORRECT_TYPE . $providerAttr); + throw new Exception(Exception::PROVIDER_INCORRECT_TYPE); } if (!empty($name)) { @@ -1211,7 +1212,7 @@ App::post('/v1/messaging/messages/email') ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(998), 'Email Subject.') ->param('description', '', new Text(256), 'Description for Message.', true) - ->param('content', '', new Text(65407), 'Email Content.') + ->param('content', '', new Text(64230), 'Email Content.') ->param('html', false, new Boolean(), 'Is content of type HTML', true) ->inject('dbForProject') ->inject('project') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 244bc1150b..ea3c865b96 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -428,9 +428,10 @@ App::post('/v1/users/:userId/targets') 'identifier' => $identifier, ])); $dbForProject->deleteCachedDocument('users', $user->getId()); + $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($target, Response::MODEL_TARGET); + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($target, Response::MODEL_TARGET); }); App::get('/v1/users') @@ -1238,7 +1239,7 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') ->setParam('targetId', $targetId); $response - ->dynamic($target, Response::MODEL_TARGET); + ->dynamic($target, Response::MODEL_TARGET); }); App::delete('/v1/users/:userId/sessions/:sessionId') diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 1a1a4fad4b..d867f98101 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -120,8 +120,8 @@ class MessagingV1 extends Worker } } finally { return [ - 'deliveredTo' => $deliveredTo, - 'deliveryErrors' => $deliveryErrors, + 'deliveredTo' => $deliveredTo, + 'deliveryErrors' => $deliveryErrors, ]; } }; diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index cbfb7981ac..999c9ee0dd 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -14,7 +14,6 @@ class Messaging extends Event parent::__construct(Event::MESSAGING_QUEUE_NAME, Event::MESSAGING_CLASS_NAME); } - /** * Sets message ID for the messaging event. * From 8e9f270ef099d2759140242257eded8f80693916 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 6 Oct 2023 03:30:47 +0530 Subject: [PATCH 69/72] update id param --- app/controllers/api/messaging.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index cc1df6ab62..72ece29eaa 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -599,7 +599,7 @@ App::get('/v1/messaging/providers') ]), Response::MODEL_PROVIDER_LIST); }); -App::get('/v1/messaging/providers/:id') +App::get('/v1/messaging/providers/:providerId') ->desc('Get Provider') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') @@ -610,11 +610,11 @@ App::get('/v1/messaging/providers/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -1166,7 +1166,7 @@ App::patch('/v1/messaging/providers/apns/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::delete('/v1/messaging/providers/:id') +App::delete('/v1/messaging/providers/:providerId') ->desc('Delete Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.delete') @@ -1179,11 +1179,11 @@ App::delete('/v1/messaging/providers/:id') ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -1252,7 +1252,7 @@ App::post('/v1/messaging/messages/email') ->dynamic($message, Response::MODEL_MESSAGE); }); -App::get('/v1/messaging/messages/:id') +App::get('/v1/messaging/messages/:messageId') ->desc('Get Message') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') @@ -1263,11 +1263,11 @@ App::get('/v1/messaging/messages/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) - ->param('id', '', new UID(), 'Message ID.') + ->param('messageId', '', new UID(), 'Message ID.') ->inject('dbForProject') ->inject('response') - ->action(function (string $id, Database $dbForProject, Response $response) { - $message = $dbForProject->getDocument('messages', $id); + ->action(function (string $messageId, Database $dbForProject, Response $response) { + $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { throw new Exception(Exception::MESSAGE_NOT_FOUND); From a92390dda2568e00de5a355af05e663d9f59512f Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 6 Oct 2023 19:23:46 +0530 Subject: [PATCH 70/72] review changes --- app/config/collections.php | 18 ++ app/config/events.php | 3 + app/controllers/api/messaging.php | 204 ++++++++++++++---- app/controllers/api/users.php | 28 ++- app/workers/messaging.php | 66 +++--- .../Utopia/Response/Model/Message.php | 9 +- tests/e2e/Services/GraphQL/Base.php | 44 ++-- tests/e2e/Services/GraphQL/MessagingTest.php | 24 +-- 8 files changed, 278 insertions(+), 118 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 1a56b160c6..bf2dd07975 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1600,6 +1600,17 @@ $commonCollections = [ 'array' => false, 'filters' => ['datetime'], ], + [ + '$id' => ID::custom('deliveredAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], [ '$id' => ID::custom('deliveryErrors'), 'type' => Database::VAR_STRING, @@ -1941,6 +1952,13 @@ $commonCollections = [ 'attributes' => ['identifier'], 'lengths' => [], 'orders' => [], + ], + [ + '$id' => ID::custom('_key_identifier_providerId'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['providerId', 'identifier'], + 'lengths' => [], + 'orders' => [], ] ], ], diff --git a/app/config/events.php b/app/config/events.php index 4aaa324e9c..b07d356470 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -258,6 +258,9 @@ return [ 'create' => [ '$description' => 'This event triggers when a message is created.', ], + 'update' => [ + '$description' => 'This event triggers when a message is updated.', + ], 'topics' => [ '$model' => Response::MODEL_TOPIC, '$resource' => true, diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 72ece29eaa..e4a008165b 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -589,7 +589,7 @@ App::get('/v1/messaging/providers') throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); } - $cursor->setValue($cursorDocument[0]); + $cursor->setValue($cursorDocument); } $filterQueries = Query::groupByType($queries)['filters']; @@ -623,7 +623,7 @@ App::get('/v1/messaging/providers/:providerId') $response->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/mailgun/:id') +App::patch('/v1/messaging/providers/mailgun/:providerId') ->desc('Update Mailgun Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -636,7 +636,7 @@ App::patch('/v1/messaging/providers/mailgun/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('isEuRegion', null, new Boolean(), 'Set as eu region.', true) @@ -645,8 +645,8 @@ App::patch('/v1/messaging/providers/mailgun/:id') ->param('domain', '', new Text(0), 'Mailgun Domain.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, ?bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -694,7 +694,7 @@ App::patch('/v1/messaging/providers/mailgun/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/sendgrid/:id') +App::patch('/v1/messaging/providers/sendgrid/:providerId') ->desc('Update Sendgrid Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -707,14 +707,14 @@ App::patch('/v1/messaging/providers/sendgrid/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -746,7 +746,7 @@ App::patch('/v1/messaging/providers/sendgrid/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/msg91/:id') +App::patch('/v1/messaging/providers/msg91/:providerId') ->desc('Update Msg91 Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -759,15 +759,15 @@ App::patch('/v1/messaging/providers/msg91/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $senderId, string $authKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -805,7 +805,7 @@ App::patch('/v1/messaging/providers/msg91/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/telesign/:id') +App::patch('/v1/messaging/providers/telesign/:providerId') ->desc('Update Telesign Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -818,15 +818,15 @@ App::patch('/v1/messaging/providers/telesign/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Telesign username.', true) ->param('password', '', new Text(0), 'Telesign password.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $username, string $password, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -864,7 +864,7 @@ App::patch('/v1/messaging/providers/telesign/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/textmagic/:id') +App::patch('/v1/messaging/providers/textmagic/:providerId') ->desc('Update Textmagic Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -877,15 +877,15 @@ App::patch('/v1/messaging/providers/textmagic/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('username', '', new Text(0), 'Textmagic username.', true) ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $username, string $apiKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -923,7 +923,7 @@ App::patch('/v1/messaging/providers/textmagic/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/twilio/:id') +App::patch('/v1/messaging/providers/twilio/:providerId') ->desc('Update Twilio Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -936,15 +936,15 @@ App::patch('/v1/messaging/providers/twilio/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $accountSid, string $authToken, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -982,7 +982,7 @@ App::patch('/v1/messaging/providers/twilio/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/vonage/:id') +App::patch('/v1/messaging/providers/vonage/:providerId') ->desc('Update Vonage Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -995,15 +995,15 @@ App::patch('/v1/messaging/providers/vonage/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('apiKey', '', new Text(0), 'Vonage API key.', true) ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $apiKey, string $apiSecret, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -1041,7 +1041,7 @@ App::patch('/v1/messaging/providers/vonage/:id') ->dynamic($provider, Response::MODEL_PROVIDER); }); -App::patch('/v1/messaging/providers/fcm/:id') +App::patch('/v1/messaging/providers/fcm/:providerId') ->desc('Update FCM Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -1054,14 +1054,14 @@ App::patch('/v1/messaging/providers/fcm/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $serverKey, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $serverKey, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -1092,7 +1092,7 @@ App::patch('/v1/messaging/providers/fcm/:id') }); -App::patch('/v1/messaging/providers/apns/:id') +App::patch('/v1/messaging/providers/apns/:providerId') ->desc('Update APNS Provider') ->groups(['api', 'messaging']) ->label('audits.event', 'providers.update') @@ -1105,7 +1105,7 @@ App::patch('/v1/messaging/providers/apns/:id') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROVIDER) - ->param('id', '', new UID(), 'Provider ID.') + ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->param('authKey', '', new Text(0), 'APNS authentication key.', true) @@ -1115,8 +1115,8 @@ App::patch('/v1/messaging/providers/apns/:id') ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $id, string $name, ?bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { - $provider = $dbForProject->getDocument('providers', $id); + ->action(function (string $providerId, string $name, ?bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { throw new Exception(Exception::PROVIDER_NOT_FOUND); @@ -1213,12 +1213,13 @@ App::post('/v1/messaging/messages/email') ->param('subject', '', new Text(998), 'Email Subject.') ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(64230), 'Email Content.') + ->param('status', 'processing', new WhiteList(['draft', 'processing']), 'Message Status.', true) ->param('html', false, new Boolean(), 'Is content of type HTML', true) ->inject('dbForProject') ->inject('project') ->inject('messaging') ->inject('response') - ->action(function (string $messageId, string $providerId, array $to, string $subject, string $description, string $content, string $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + ->action(function (string $messageId, string $providerId, array $to, string $subject, string $description, string $content, string $status, bool $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; $provider = $dbForProject->getDocument('providers', $providerId); @@ -1238,20 +1239,63 @@ App::post('/v1/messaging/messages/email') 'html' => $html, 'description' => $description, ], - 'status' => 'processing', + 'status' => $status, 'search' => $messageId . ' ' . $description . ' ' . $subject, ])); - $messaging - ->setMessageId($message->getId()) - ->setProject($project) - ->trigger(); + if ($status === 'processing') { + $messaging + ->setMessageId($message->getId()) + ->setProject($project) + ->trigger(); + } $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($message, Response::MODEL_MESSAGE); }); +App::get('/v1/messaging/messages') + ->desc('List Messages') + ->groups(['api', 'messaging']) + ->label('scope', 'messages.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'listMessages') + ->label('sdk.description', '/docs/references/messaging/list-messages.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_MESSAGE_LIST) + ->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) + ->inject('dbForProject') + ->inject('response') + ->action(function (array $queries, Database $dbForProject, Response $response) { + $queries = Query::parseQueries($queries); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); + + if ($cursor) { + $messageId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->findOne('messages', [ + Query::equal('$id', [$messageId]), + ])); + + if ($cursorDocument === false || $cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('messages', $filterQueries, APP_LIMIT_COUNT), + 'messages' => $dbForProject->find('messages', $queries), + ]), Response::MODEL_MESSAGE_LIST); + }); + App::get('/v1/messaging/messages/:messageId') ->desc('Get Message') ->groups(['api', 'messaging']) @@ -1275,3 +1319,77 @@ App::get('/v1/messaging/messages/:messageId') $response->dynamic($message, Response::MODEL_MESSAGE); }); + +App::post('/v1/messaging/messages/email/:messageId') + ->desc('Update an email.') + ->groups(['api', 'messaging']) + ->label('audits.event', 'messages.update') + ->label('audits.resource', 'messages/{response.$id}') + ->label('scope', 'messages.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'messaging') + ->label('sdk.method', 'updateEmail') + ->label('sdk.description', '/docs/references/messaging/update-email.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->param('messageId', '', new UID(), 'Message ID.') + ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs or List of User IDs or List of Target IDs.', true) + ->param('subject', '', new Text(998), 'Email Subject.', true) + ->param('description', '', new Text(256), 'Description for Message.', true) + ->param('content', '', new Text(64230), 'Email Content.', true) + ->param('status', '', new WhiteList(['draft', 'processing']), 'Message Status.', true) + ->param('html', false, new Boolean(), 'Is content of type HTML', true) + ->inject('dbForProject') + ->inject('project') + ->inject('messaging') + ->inject('response') + ->action(function (string $messageId, array $to, string $subject, string $description, string $content, string $status, bool $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + $message = $dbForProject->getDocument('messages', $messageId); + + if ($message->isEmpty()) { + throw new Exception(Exception::MESSAGE_NOT_FOUND); + } + + if (\count($to) > 0) { + $message->setAttribute('to', $to); + } + + $data = $message->getAttribute('data'); + + if (!empty($subject)) { + $data['subject'] = $subject; + } + + if (!empty($content)) { + $data['content'] = $content; + } + + if (!empty($description)) { + $data['description'] = $description; + } + + if (!empty($html)) { + $data['html'] = $html; + } + + $message->setAttribute('data', $data); + $message->setAttribute('search', $message->getId() . ' ' . $data['description'] . ' ' . $data['subject']); + + if (!empty($status)) { + $message->setAttribute('status', $status); + } + + $message = $dbForProject->updateDocument('messages', $message->getId(), $message); + + if ($status === 'processing') { + $messaging + ->setMessageId($message->getId()) + ->setProject($project) + ->trigger(); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($message, Response::MODEL_MESSAGE); + }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index e4ab995e19..9551a05ed9 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -419,14 +419,18 @@ App::post('/v1/users/:userId/targets') throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); } - $target = $dbForProject->createDocument('targets', new Document([ - '$id' => $targetId, - 'providerId' => $providerId, - 'providerInternalId' => $provider->getInternalId(), - 'userId' => $userId, - 'userInternalId' => $user->getInternalId(), - 'identifier' => $identifier, - ])); + try { + $target = $dbForProject->createDocument('targets', new Document([ + '$id' => $targetId, + 'providerId' => $providerId, + 'providerInternalId' => $provider->getInternalId(), + 'userId' => $userId, + 'userInternalId' => $user->getInternalId(), + 'identifier' => $identifier, + ])); + } catch (Duplicate) { + throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); + } $dbForProject->deleteCachedDocument('users', $user->getId()); $response @@ -1229,6 +1233,10 @@ App::patch('/v1/users/:userId/targets/:targetId/identifier') throw new Exception(Exception::USER_TARGET_NOT_FOUND); } + if ($user->getId() !== $target->getAttribute('userId')) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + $target->setAttribute('identifier', $identifier); $target = $dbForProject->updateDocument('targets', $target->getId(), $target); @@ -1404,6 +1412,10 @@ App::delete('/v1/users/:userId/targets/:targetId') throw new Exception(Exception::USER_TARGET_NOT_FOUND); } + if ($user->getId() !== $target->getAttribute('userId')) { + throw new Exception(Exception::USER_TARGET_NOT_FOUND); + } + $target = $dbForProject->deleteDocument('targets', $target->getId()); $dbForProject->deleteCachedDocument('users', $user->getId()); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index d867f98101..14a08e8cfa 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -62,16 +62,16 @@ class MessagingV1 extends Worker $this->processMessage($message, $provider); } - private function processMessage(Document $messageRecord, Document $providerRecord): void + private function processMessage(Document $message, Document $provider): void { - $provider = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->sms($providerRecord), - 'push' => $this->push($providerRecord), - 'email' => $this->email($providerRecord), + $adapter = match ($provider->getAttribute('type')) { + 'sms' => $this->sms($provider), + 'push' => $this->push($provider), + 'email' => $this->email($provider), default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE) }; - $recipientsId = $messageRecord->getAttribute('to'); + $recipientsId = $message->getAttribute('to'); /** * @var Document[] $recipients @@ -90,29 +90,31 @@ class MessagingV1 extends Worker $targets = $this->dbForProject->find('targets', [Query::equal('$id', $recipientsId)]); $recipients = \array_merge($recipients, $targets); - $recipients = \array_filter($recipients, fn (Document $recipient) => $recipient->getAttribute('providerId') === $providerRecord->getId()); + $recipients = \array_filter($recipients, function (Document $recipient) use ($provider) { + return $recipient->getAttribute('providerId') === $provider->getId(); + }); $identifiers = \array_map(function (Document $recipient) { return $recipient->getAttribute('identifier'); }, $recipients); - $maxBatchSize = $provider->getMaxMessagesPerRequest(); + $maxBatchSize = $adapter->getMaxMessagesPerRequest(); $batches = \array_chunk($identifiers, $maxBatchSize); - $results = batch(\array_map(function ($batch) use ($messageRecord, $providerRecord, $provider) { - return function () use ($batch, $messageRecord, $providerRecord, $provider) { + $results = batch(\array_map(function ($batch) use ($message, $provider, $adapter) { + return function () use ($batch, $message, $provider, $adapter) { $deliveredTo = 0; $deliveryErrors = []; - $messageData = clone $messageRecord; + $messageData = clone $message; $messageData->setAttribute('to', $batch); - $message = match ($providerRecord->getAttribute('type')) { - 'sms' => $this->buildSMSMessage($messageData, $providerRecord), + $data = match ($provider->getAttribute('type')) { + 'sms' => $this->buildSMSMessage($messageData, $provider), 'push' => $this->buildPushMessage($messageData), - 'email' => $this->buildEmailMessage($messageData, $providerRecord), + 'email' => $this->buildEmailMessage($messageData, $provider), default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE) }; try { - $provider->send($message); + $adapter->send($data); $deliveredTo += \count($batch); } catch (\Exception $e) { foreach ($batch as $identifier) { @@ -133,28 +135,28 @@ class MessagingV1 extends Worker $deliveredTo += $result['deliveredTo']; $deliveryErrors = \array_merge($deliveryErrors, $result['deliveryErrors']); } - $messageRecord->setAttribute('deliveryErrors', $deliveryErrors); + $message->setAttribute('deliveryErrors', $deliveryErrors); - if (\count($messageRecord->getAttribute('deliveryErrors')) > 0) { - $messageRecord->setAttribute('status', 'failed'); + if (\count($message->getAttribute('deliveryErrors')) > 0) { + $message->setAttribute('status', 'failed'); } else { - $messageRecord->setAttribute('status', 'sent'); + $message->setAttribute('status', 'sent'); } - $messageRecord->setAttribute('to', $recipientsId); - $messageRecord->setAttribute('deliveredTo', $deliveredTo); - $messageRecord->setAttribute('deliveryTime', DateTime::now()); + $message->setAttribute('to', $recipientsId); + $message->setAttribute('deliveredTo', $deliveredTo); + $message->setAttribute('deliveredAt', DateTime::now()); - $this->dbForProject->updateDocument('messages', $messageRecord->getId(), $messageRecord); + $this->dbForProject->updateDocument('messages', $message->getId(), $message); } public function shutdown(): void { } - private function sms(Document $document): ?SMSAdapter + private function sms(Document $provider): ?SMSAdapter { - $credentials = $document->getAttribute('credentials'); - return match ($document->getAttribute('provider')) { + $credentials = $provider->getAttribute('credentials'); + return match ($provider->getAttribute('provider')) { 'mock' => new Mock('username', 'password'), 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']), 'text-magic' => new TextMagic($credentials['username'], $credentials['apiKey']), @@ -165,10 +167,10 @@ class MessagingV1 extends Worker }; } - private function push(Document $document): ?PushAdapter + private function push(Document $provider): ?PushAdapter { - $credentials = $document->getAttribute('credentials'); - return match ($document->getAttribute('provider')) { + $credentials = $provider->getAttribute('credentials'); + return match ($provider->getAttribute('provider')) { 'apns' => new APNS( $credentials['authKey'], $credentials['authKeyId'], @@ -181,10 +183,10 @@ class MessagingV1 extends Worker }; } - private function email(Document $document): ?EmailAdapter + private function email(Document $provider): ?EmailAdapter { - $credentials = $document->getAttribute('credentials'); - return match ($document->getAttribute('provider')) { + $credentials = $provider->getAttribute('credentials'); + return match ($provider->getAttribute('provider')) { 'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']), 'sendgrid' => new SendGrid($credentials['apiKey']), default => null diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 2f75997048..5e4a358490 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -32,11 +32,18 @@ class Message extends Any ]) ->addRule('deliveryTime', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Time the message is delivered at.', + 'description' => 'The scheduled time for message.', 'required' => false, 'default' => DateTime::now(), 'example' => self::TYPE_DATETIME_EXAMPLE, ]) + ->addRule('deliveredAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'The time when the message was delivered.', + 'required' => false, + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ->addRule('deliveryErrors', [ 'type' => self::TYPE_STRING, 'description' => 'Delivery errors if any.', diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 3a7859662a..0a93ac34c4 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1823,8 +1823,8 @@ trait Base } }'; case self::$GET_PROVIDER: - return 'query getProvider($id: String!) { - messagingGetProvider(id: $id) { + return 'query getProvider($providerId: String!) { + messagingGetProvider(providerId: $providerId) { _id name provider @@ -1834,8 +1834,8 @@ trait Base } }'; case self::$UPDATE_MAILGUN_PROVIDER: - return 'mutation updateMailgunProvider($id: String!, $name: String!, $domain: String!, $apiKey: String!, $isEuRegion: Boolean, $enabled: Boolean) { - messagingUpdateMailgunProvider(id: $id, name: $name, domain: $domain, apiKey: $apiKey, isEuRegion: $isEuRegion, enabled: $enabled) { + return 'mutation updateMailgunProvider($providerId: String!, $name: String!, $domain: String!, $apiKey: String!, $isEuRegion: Boolean, $enabled: Boolean) { + messagingUpdateMailgunProvider(providerId: $providerId, name: $name, domain: $domain, apiKey: $apiKey, isEuRegion: $isEuRegion, enabled: $enabled) { _id name provider @@ -1845,8 +1845,8 @@ trait Base } }'; case self::$UPDATE_SENDGRID_PROVIDER: - return 'mutation messagingUpdateSendgridProvider($id: String!, $name: String!, $apiKey: String!) { - messagingUpdateSendgridProvider(id: $id, name: $name, apiKey: $apiKey) { + return 'mutation messagingUpdateSendgridProvider($providerId: String!, $name: String!, $apiKey: String!) { + messagingUpdateSendgridProvider(providerId: $providerId, name: $name, apiKey: $apiKey) { _id name provider @@ -1856,8 +1856,8 @@ trait Base } }'; case self::$UPDATE_TWILIO_PROVIDER: - return 'mutation updateTwilioProvider($id: String!, $name: String!, $accountSid: String!, $authToken: String!) { - messagingUpdateTwilioProvider(id: $id, name: $name, accountSid: $accountSid, authToken: $authToken) { + return 'mutation updateTwilioProvider($providerId: String!, $name: String!, $accountSid: String!, $authToken: String!) { + messagingUpdateTwilioProvider(providerId: $providerId, name: $name, accountSid: $accountSid, authToken: $authToken) { _id name provider @@ -1867,8 +1867,8 @@ trait Base } }'; case self::$UPDATE_TELESIGN_PROVIDER: - return 'mutation updateTelesignProvider($id: String!, $name: String!, $username: String!, $password: String!) { - messagingUpdateTelesignProvider(id: $id, name: $name, username: $username, password: $password) { + return 'mutation updateTelesignProvider($providerId: String!, $name: String!, $username: String!, $password: String!) { + messagingUpdateTelesignProvider(providerId: $providerId, name: $name, username: $username, password: $password) { _id name provider @@ -1878,8 +1878,8 @@ trait Base } }'; case self::$UPDATE_TEXTMAGIC_PROVIDER: - return 'mutation updateTextmagicProvider($id: String!, $name: String!, $username: String!, $apiKey: String!) { - messagingUpdateTextmagicProvider(id: $id, name: $name, username: $username, apiKey: $apiKey) { + return 'mutation updateTextmagicProvider($providerId: String!, $name: String!, $username: String!, $apiKey: String!) { + messagingUpdateTextmagicProvider(providerId: $providerId, name: $name, username: $username, apiKey: $apiKey) { _id name provider @@ -1889,8 +1889,8 @@ trait Base } }'; case self::$UPDATE_MSG91_PROVIDER: - return 'mutation updateMsg91Provider($id: String!, $name: String!, $senderId: String!, $authKey: String!) { - messagingUpdateMsg91Provider(id: $id, name: $name, senderId: $senderId, authKey: $authKey) { + return 'mutation updateMsg91Provider($providerId: String!, $name: String!, $senderId: String!, $authKey: String!) { + messagingUpdateMsg91Provider(providerId: $providerId, name: $name, senderId: $senderId, authKey: $authKey) { _id name provider @@ -1900,8 +1900,8 @@ trait Base } }'; case self::$UPDATE_VONAGE_PROVIDER: - return 'mutation updateVonageProvider($id: String!, $name: String!, $apiKey: String!, $apiSecret: String!) { - messagingUpdateVonageProvider(id: $id, name: $name, apiKey: $apiKey, apiSecret: $apiSecret) { + return 'mutation updateVonageProvider($providerId: String!, $name: String!, $apiKey: String!, $apiSecret: String!) { + messagingUpdateVonageProvider(providerId: $providerId, name: $name, apiKey: $apiKey, apiSecret: $apiSecret) { _id name provider @@ -1911,8 +1911,8 @@ trait Base } }'; case self::$UPDATE_FCM_PROVIDER: - return 'mutation updateFcmProvider($id: String!, $name: String!, $serverKey: String!) { - messagingUpdateFcmProvider(id: $id, name: $name, serverKey: $serverKey) { + return 'mutation updateFcmProvider($providerId: String!, $name: String!, $serverKey: String!) { + messagingUpdateFcmProvider(providerId: $providerId, name: $name, serverKey: $serverKey) { _id name provider @@ -1922,8 +1922,8 @@ trait Base } }'; case self::$UPDATE_APNS_PROVIDER: - return 'mutation updateApnsProvider($id: String!, $name: String!, $authKey: String!, $authKeyId: String!, $teamId: String!, $bundleId: String!, $endpoint: String!) { - messagingUpdateApnsProvider(id: $id, name: $name, authKey: $authKey, authKeyId: $authKeyId, teamId: $teamId, bundleId: $bundleId, endpoint: $endpoint) { + return 'mutation updateApnsProvider($providerId: String!, $name: String!, $authKey: String!, $authKeyId: String!, $teamId: String!, $bundleId: String!, $endpoint: String!) { + messagingUpdateApnsProvider(providerId: $providerId, name: $name, authKey: $authKey, authKeyId: $authKeyId, teamId: $teamId, bundleId: $bundleId, endpoint: $endpoint) { _id name provider @@ -1933,8 +1933,8 @@ trait Base } }'; case self::$DELETE_PROVIDER: - return 'mutation deleteProvider($id: String!) { - messagingDeleteProvider(id: $id) { + return 'mutation deleteProvider($providerId: String!) { + messagingDeleteProvider(providerId: $providerId) { status } }'; diff --git a/tests/e2e/Services/GraphQL/MessagingTest.php b/tests/e2e/Services/GraphQL/MessagingTest.php index 1bc5e70477..99bad52887 100644 --- a/tests/e2e/Services/GraphQL/MessagingTest.php +++ b/tests/e2e/Services/GraphQL/MessagingTest.php @@ -104,53 +104,53 @@ class MessagingTest extends Scope { $providersParams = [ 'Sendgrid' => [ - 'id' => $providers[0]['_id'], + 'providerId' => $providers[0]['_id'], 'name' => 'Sengrid2', 'apiKey' => 'my-apikey', ], 'Mailgun' => [ - 'id' => $providers[1]['_id'], + 'providerId' => $providers[1]['_id'], 'name' => 'Mailgun2', 'apiKey' => 'my-apikey', 'domain' => 'my-domain', ], 'Twilio' => [ - 'id' => $providers[2]['_id'], + 'providerId' => $providers[2]['_id'], 'name' => 'Twilio2', 'accountSid' => 'my-accountSid', 'authToken' => 'my-authToken', ], 'Telesign' => [ - 'id' => $providers[3]['_id'], + 'providerId' => $providers[3]['_id'], 'name' => 'Telesign2', 'username' => 'my-username', 'password' => 'my-password', ], 'Textmagic' => [ - 'id' => $providers[4]['_id'], + 'providerId' => $providers[4]['_id'], 'name' => 'Textmagic2', 'username' => 'my-username', 'apiKey' => 'my-apikey', ], 'Msg91' => [ - 'id' => $providers[5]['_id'], + 'providerId' => $providers[5]['_id'], 'name' => 'Ms91-2', 'senderId' => 'my-senderid', 'authKey' => 'my-authkey', ], 'Vonage' => [ - 'id' => $providers[6]['_id'], + 'providerId' => $providers[6]['_id'], 'name' => 'Vonage2', 'apiKey' => 'my-apikey', 'apiSecret' => 'my-apisecret', ], 'Fcm' => [ - 'id' => $providers[7]['_id'], + 'providerId' => $providers[7]['_id'], 'name' => 'FCM2', 'serverKey' => 'my-serverkey', ], 'Apns' => [ - 'id' => $providers[8]['_id'], + 'providerId' => $providers[8]['_id'], 'name' => 'APNS2', 'authKey' => 'my-authkey', 'authKeyId' => 'my-authkeyid', @@ -182,7 +182,7 @@ class MessagingTest extends Scope ], [ 'query' => $this->getQuery('update_mailgun_provider'), 'variables' => [ - 'id' => $providers[1]['_id'], + 'providerId' => $providers[1]['_id'], 'name' => 'Mailgun2', 'apiKey' => 'my-apikey', 'domain' => 'my-domain', @@ -224,7 +224,7 @@ class MessagingTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'id' => $providers[0]['_id'], + 'providerId' => $providers[0]['_id'], ] ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -246,7 +246,7 @@ class MessagingTest extends Scope $graphQLPayload = [ 'query' => $query, 'variables' => [ - 'id' => $provider['_id'], + 'providerId' => $provider['_id'], ] ]; $response = $this->client->call(Client::METHOD_POST, '/graphql', [ From a77a212e2c80dc60db5d0ae3431cfb97d9c65e4d Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Mon, 9 Oct 2023 17:29:26 +0530 Subject: [PATCH 71/72] adds scheduling for messaging worker --- app/controllers/api/messaging.php | 5 ++++- src/Appwrite/Event/Messaging.php | 36 +++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e4a008165b..f4718e55b2 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -21,6 +21,7 @@ use Utopia\Validator\Boolean; use Utopia\Validator\JSON; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; +use Utopia\Database\DateTime; App::post('/v1/messaging/providers/mailgun') ->desc('Create Mailgun Provider') @@ -1340,11 +1341,12 @@ App::post('/v1/messaging/messages/email/:messageId') ->param('content', '', new Text(64230), 'Email Content.', true) ->param('status', '', new WhiteList(['draft', 'processing']), 'Message Status.', true) ->param('html', false, new Boolean(), 'Is content of type HTML', true) + ->param('deliveryTime', DateTime::now(), new DatetimeValidator(), 'Delivery time for message.', true) ->inject('dbForProject') ->inject('project') ->inject('messaging') ->inject('response') - ->action(function (string $messageId, array $to, string $subject, string $description, string $content, string $status, bool $html, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { + ->action(function (string $messageId, array $to, string $subject, string $description, string $content, string $status, bool $html, string $deliveryTime, Database $dbForProject, Document $project, Messaging $messaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -1385,6 +1387,7 @@ App::post('/v1/messaging/messages/email/:messageId') if ($status === 'processing') { $messaging ->setMessageId($message->getId()) + ->setDeliveryTime($deliveryTime) ->setProject($project) ->trigger(); } diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index 999c9ee0dd..18887ffcd3 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -2,12 +2,13 @@ namespace Appwrite\Event; -use Resque; -use Utopia\Database\Document; +use ResqueScheduler; +use Utopia\Database\DateTime; class Messaging extends Event { protected ?string $messageId = null; + private ?string $deliveryTime = null; public function __construct() { @@ -38,17 +39,38 @@ class Messaging extends Event } /** - * Executes the event and sends it to the messaging worker. + * Sets Delivery time for the messaging event. * - * @return string|bool - * @throws \InvalidArgumentException + * @param string $deliveryTime + * @return self */ - public function trigger(): string|bool + public function setDeliveryTime(string $deliveryTime): self { - return Resque::enqueue($this->queue, $this->class, [ + $this->deliveryTime = $deliveryTime; + + return $this; + } + + /** + * Returns set Delivery Time for the messaging event. + * + * @return string + */ + public function getDeliveryTime(): string + { + return $this->deliveryTime; + } + + /** + * Executes the event and sends it to the messaging worker. + */ + public function trigger(): string | bool + { + ResqueScheduler::enqueueAt(!empty($this->deliveryTime) ? $this->deliveryTime : DateTime::now(), $this->queue, $this->class, [ 'project' => $this->project, 'user' => $this->user, 'messageId' => $this->messageId, ]); + return true; } } From cc1769ed41e2bed120111490a9b033f7baacb0ce Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 12 Oct 2023 11:48:26 +0530 Subject: [PATCH 72/72] review changes --- app/controllers/api/messaging.php | 3 +-- app/workers/messaging.php | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index f4718e55b2..533086a058 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1321,7 +1321,7 @@ App::get('/v1/messaging/messages/:messageId') $response->dynamic($message, Response::MODEL_MESSAGE); }); -App::post('/v1/messaging/messages/email/:messageId') +App::patch('/v1/messaging/messages/email/:messageId') ->desc('Update an email.') ->groups(['api', 'messaging']) ->label('audits.event', 'messages.update') @@ -1393,6 +1393,5 @@ App::post('/v1/messaging/messages/email/:messageId') } $response - ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($message, Response::MODEL_MESSAGE); }); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 14a08e8cfa..8432e43d80 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -100,9 +100,10 @@ class MessagingV1 extends Worker $maxBatchSize = $adapter->getMaxMessagesPerRequest(); $batches = \array_chunk($identifiers, $maxBatchSize); + $batchIndex = 0; - $results = batch(\array_map(function ($batch) use ($message, $provider, $adapter) { - return function () use ($batch, $message, $provider, $adapter) { + $results = batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex) { + return function () use ($batch, $message, $provider, $adapter, $batchIndex) { $deliveredTo = 0; $deliveryErrors = []; $messageData = clone $message; @@ -117,10 +118,9 @@ class MessagingV1 extends Worker $adapter->send($data); $deliveredTo += \count($batch); } catch (\Exception $e) { - foreach ($batch as $identifier) { - $deliveryErrors[] = 'Failed to send message to target' . $identifier . ': ' . $e->getMessage(); - } + $deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage(); } finally { + $batchIndex++; return [ 'deliveredTo' => $deliveredTo, 'deliveryErrors' => $deliveryErrors,