From 7573ee75a224d2012a99d14681e4d2d28b6da7d9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 7 Jan 2026 20:04:28 +1300 Subject: [PATCH 01/52] Use authorization instance --- app/cli.php | 28 ++-- app/config/storage/resource_limits.php | 4 +- app/controllers/api/account.php | 146 ++++++++++-------- app/controllers/api/avatars.php | 29 ++-- app/controllers/api/graphql.php | 5 +- app/controllers/api/health.php | 12 +- app/controllers/api/messaging.php | 65 ++++---- app/controllers/api/migrations.php | 14 +- app/controllers/api/project.php | 9 +- app/controllers/api/teams.php | 63 ++++---- app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 60 +++---- app/controllers/general.php | 74 +++++---- app/controllers/shared/api.php | 53 ++++--- app/controllers/shared/api/auth.php | 7 +- app/http.php | 28 ++-- app/init/database/filters.php | 47 +++--- app/init/resources.php | 106 +++++++------ app/realtime.php | 41 +++-- app/worker.php | 53 ++++--- composer.json | 10 +- composer.lock | 79 +++++----- src/Appwrite/Databases/TransactionState.php | 10 +- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Compute/Base.php | 41 ++++- .../Modules/Console/Http/Resources/Get.php | 6 +- .../Collections/Attributes/Action.php | 10 +- .../Collections/Attributes/Boolean/Create.php | 6 +- .../Collections/Attributes/Boolean/Update.php | 5 +- .../Attributes/Datetime/Create.php | 7 +- .../Attributes/Datetime/Update.php | 5 +- .../Collections/Attributes/Delete.php | 5 +- .../Collections/Attributes/Email/Create.php | 7 +- .../Collections/Attributes/Email/Update.php | 5 +- .../Collections/Attributes/Enum/Create.php | 7 +- .../Collections/Attributes/Enum/Update.php | 5 +- .../Collections/Attributes/Float/Create.php | 6 +- .../Collections/Attributes/Float/Update.php | 5 +- .../Databases/Collections/Attributes/Get.php | 5 +- .../Collections/Attributes/IP/Create.php | 7 +- .../Collections/Attributes/IP/Update.php | 5 +- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Integer/Update.php | 5 +- .../Collections/Attributes/Line/Create.php | 6 +- .../Collections/Attributes/Line/Update.php | 5 +- .../Collections/Attributes/Point/Create.php | 6 +- .../Collections/Attributes/Point/Update.php | 5 +- .../Collections/Attributes/Polygon/Create.php | 6 +- .../Collections/Attributes/Polygon/Update.php | 5 +- .../Attributes/Relationship/Create.php | 7 +- .../Attributes/Relationship/Update.php | 6 +- .../Collections/Attributes/String/Create.php | 8 +- .../Collections/Attributes/String/Update.php | 6 +- .../Collections/Attributes/URL/Create.php | 7 +- .../Collections/Attributes/URL/Update.php | 6 +- .../Collections/Attributes/XList.php | 5 +- .../Http/Databases/Collections/Create.php | 5 +- .../Http/Databases/Collections/Delete.php | 5 +- .../Collections/Documents/Action.php | 7 +- .../Documents/Attribute/Decrement.php | 13 +- .../Documents/Attribute/Increment.php | 13 +- .../Collections/Documents/Create.php | 43 +++--- .../Collections/Documents/Delete.php | 17 +- .../Databases/Collections/Documents/Get.php | 12 +- .../Collections/Documents/Logs/XList.php | 5 +- .../Collections/Documents/Update.php | 26 ++-- .../Collections/Documents/Upsert.php | 26 ++-- .../Databases/Collections/Documents/XList.php | 16 +- .../Http/Databases/Collections/Get.php | 5 +- .../Databases/Collections/Indexes/Create.php | 5 +- .../Databases/Collections/Indexes/Delete.php | 5 +- .../Databases/Collections/Indexes/Get.php | 5 +- .../Databases/Collections/Indexes/XList.php | 7 +- .../Http/Databases/Collections/Logs/XList.php | 39 ++--- .../Http/Databases/Collections/Update.php | 5 +- .../Http/Databases/Collections/Usage/Get.php | 5 +- .../Http/Databases/Collections/XList.php | 5 +- .../Http/Databases/Transactions/Create.php | 5 +- .../Transactions/Operations/Create.php | 34 ++-- .../Http/Databases/Transactions/Update.php | 37 ++--- .../Databases/Http/Databases/Usage/Get.php | 5 +- .../Databases/Http/Databases/Usage/XList.php | 5 +- .../Tables/Columns/Boolean/Create.php | 1 + .../Tables/Columns/Boolean/Update.php | 1 + .../Tables/Columns/Datetime/Create.php | 1 + .../Tables/Columns/Datetime/Update.php | 1 + .../Http/TablesDB/Tables/Columns/Delete.php | 1 + .../TablesDB/Tables/Columns/Email/Create.php | 1 + .../TablesDB/Tables/Columns/Email/Update.php | 1 + .../TablesDB/Tables/Columns/Enum/Create.php | 1 + .../TablesDB/Tables/Columns/Enum/Update.php | 1 + .../TablesDB/Tables/Columns/Float/Create.php | 1 + .../TablesDB/Tables/Columns/Float/Update.php | 1 + .../Http/TablesDB/Tables/Columns/Get.php | 1 + .../TablesDB/Tables/Columns/IP/Create.php | 1 + .../TablesDB/Tables/Columns/IP/Update.php | 1 + .../Tables/Columns/Integer/Create.php | 1 + .../Tables/Columns/Integer/Update.php | 1 + .../TablesDB/Tables/Columns/Line/Create.php | 1 + .../TablesDB/Tables/Columns/Line/Update.php | 1 + .../TablesDB/Tables/Columns/Point/Create.php | 1 + .../TablesDB/Tables/Columns/Point/Update.php | 1 + .../Tables/Columns/Polygon/Create.php | 1 + .../Tables/Columns/Polygon/Update.php | 1 + .../Tables/Columns/Relationship/Create.php | 1 + .../Tables/Columns/Relationship/Update.php | 1 + .../TablesDB/Tables/Columns/String/Create.php | 1 + .../TablesDB/Tables/Columns/String/Update.php | 1 + .../TablesDB/Tables/Columns/URL/Create.php | 1 + .../TablesDB/Tables/Columns/URL/Update.php | 1 + .../Http/TablesDB/Tables/Columns/XList.php | 1 + .../Databases/Http/TablesDB/Tables/Create.php | 1 + .../Databases/Http/TablesDB/Tables/Delete.php | 1 + .../Databases/Http/TablesDB/Tables/Get.php | 1 + .../Http/TablesDB/Tables/Indexes/Create.php | 2 + .../Http/TablesDB/Tables/Indexes/Delete.php | 1 + .../Http/TablesDB/Tables/Indexes/Get.php | 1 + .../Http/TablesDB/Tables/Indexes/XList.php | 1 + .../Http/TablesDB/Tables/Logs/XList.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Delete.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Update.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Upsert.php | 1 + .../TablesDB/Tables/Rows/Column/Decrement.php | 1 + .../TablesDB/Tables/Rows/Column/Increment.php | 1 + .../Http/TablesDB/Tables/Rows/Create.php | 1 + .../Http/TablesDB/Tables/Rows/Delete.php | 1 + .../Http/TablesDB/Tables/Rows/Get.php | 1 + .../Http/TablesDB/Tables/Rows/Logs/XList.php | 1 + .../Http/TablesDB/Tables/Rows/Update.php | 1 + .../Http/TablesDB/Tables/Rows/Upsert.php | 1 + .../Http/TablesDB/Tables/Rows/XList.php | 1 + .../Databases/Http/TablesDB/Tables/Update.php | 1 + .../Http/TablesDB/Tables/Usage/Get.php | 1 + .../Databases/Http/TablesDB/Tables/XList.php | 1 + .../Http/TablesDB/Transactions/Create.php | 1 + .../Transactions/Operations/Create.php | 1 + .../Http/TablesDB/Transactions/Update.php | 1 + .../Databases/Http/TablesDB/Usage/Get.php | 1 + .../Databases/Http/TablesDB/Usage/XList.php | 1 + .../Functions/Http/Deployments/Create.php | 5 +- .../Http/Deployments/Template/Create.php | 12 +- .../Functions/Http/Deployments/Vcs/Create.php | 2 +- .../Functions/Http/Executions/Create.php | 25 +-- .../Functions/Http/Executions/Delete.php | 6 +- .../Modules/Functions/Http/Executions/Get.php | 10 +- .../Functions/Http/Executions/XList.php | 10 +- .../Functions/Http/Functions/Create.php | 9 +- .../Functions/Http/Functions/Delete.php | 6 +- .../Http/Functions/Deployment/Update.php | 10 +- .../Functions/Http/Functions/Update.php | 6 +- .../Modules/Functions/Http/Usage/Get.php | 5 +- .../Modules/Functions/Http/Usage/XList.php | 5 +- .../Functions/Http/Variables/Create.php | 6 +- .../Functions/Http/Variables/Delete.php | 6 +- .../Functions/Http/Variables/Update.php | 6 +- .../Modules/Functions/Workers/Builds.php | 16 +- .../Modules/Sites/Http/Deployments/Create.php | 10 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Template/Create.php | 9 +- .../Sites/Http/Deployments/Vcs/Create.php | 6 +- .../Sites/Http/Sites/Deployment/Update.php | 8 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 6 +- .../Modules/Sites/Http/Usage/XList.php | 5 +- .../Http/Tokens/Buckets/Files/Action.php | 17 +- .../Http/Tokens/Buckets/Files/Create.php | 11 +- .../Http/Tokens/Buckets/Files/XList.php | 6 +- src/Appwrite/Platform/Tasks/Migrate.php | 9 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 3 +- .../Platform/Tasks/StatsResources.php | 5 +- src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Platform/Workers/Functions.php | 2 - src/Appwrite/Platform/Workers/Migrations.php | 18 ++- .../Utopia/Database/Documents/User.php | 5 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 5 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 25 ++- .../DatabasesPermissionsGuestTest.php | 25 ++- tests/e2e/Services/Tokens/TokensBase.php | 8 +- .../unit/Messaging/MessagingChannelsTest.php | 18 ++- .../Utopia/Database/Documents/UserTest.php | 33 ++-- 182 files changed, 1230 insertions(+), 776 deletions(-) diff --git a/app/cli.php b/app/cli.php index 07966b2450..7493d10ab3 100644 --- a/app/cli.php +++ b/app/cli.php @@ -41,8 +41,6 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false)); // require controllers after overwriting runtimes require_once __DIR__ . '/controllers/general.php'; -Authorization::disable(); - CLI::setResource('register', fn () => $register); CLI::setResource('cache', function ($pools) { @@ -60,7 +58,13 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('dbForPlatform', function ($pools, $cache) { +CLI::setResource('authorization', function () { + $authorization = new Authorization(); + $authorization->disable(); + return $authorization; +}, []); + +CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -74,6 +78,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -99,7 +104,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { } return $dbForPlatform; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('console', function () { return new Document(Config::getParam('console')); @@ -110,10 +115,10 @@ CLI::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -146,6 +151,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); + $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -162,17 +168,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { +CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -182,6 +189,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) @@ -194,7 +202,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); diff --git a/app/config/storage/resource_limits.php b/app/config/storage/resource_limits.php index cfbcea5a47..43ed2b8b05 100644 --- a/app/config/storage/resource_limits.php +++ b/app/config/storage/resource_limits.php @@ -3,4 +3,6 @@ use Utopia\Image\Image; use Utopia\System\System; -Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); +if (\class_exists('Imagick')) { + Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); +} diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 2c481b500c..bcea3387a2 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -207,10 +207,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr } -$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $userFromRequest */ - $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -266,7 +266,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -275,7 +275,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + $authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -376,8 +376,9 @@ App::post('/v1/account') ->inject('user') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('hooks') - ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Hooks $hooks) { + ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Hooks $hooks) { $email = \strtolower($email); if ('console' === $project->getId()) { @@ -469,9 +470,9 @@ App::post('/v1/account') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -497,9 +498,9 @@ App::post('/v1/account') throw new Exception(Exception::USER_ALREADY_EXISTS); } - Authorization::unsetRole(Role::guests()->toString()); - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $authorization->removeRole(Role::guests()->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::users()->toString()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -976,7 +977,8 @@ App::post('/v1/account/sessions/email') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -1021,7 +1023,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) { @@ -1120,7 +1122,8 @@ App::post('/v1/account/sessions/anonymous') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1165,7 +1168,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; @@ -1191,7 +1194,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -1274,6 +1277,7 @@ App::post('/v1/account/sessions/token') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') +->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1470,7 +1474,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) { + ->inject('authorization') + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1726,7 +1731,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ]); $user->removeAttribute('$sequence'); - $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $userDoc = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), @@ -1744,8 +1749,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::users()->toString()); if (false === $user->getAttribute('status')) { // Account is blocked $failureRedirect(Exception::USER_BLOCKED); // User is in status blocked @@ -1816,7 +1821,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1840,7 +1845,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2077,7 +2082,8 @@ App::post('/v1/account/tokens/magic-url') ->inject('queueForMails') ->inject('proofForPassword') ->inject('platform') - ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform) { + ->inject('authorization') + ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2150,7 +2156,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); } $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); @@ -2170,7 +2176,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2356,7 +2362,8 @@ App::post('/v1/account/tokens/email') ->inject('queueForMails') ->inject('proofForPassword') ->inject('proofForCode') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2425,9 +2432,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2465,7 +2472,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2662,10 +2669,11 @@ App::put('/v1/account/sessions/magic-url') ->inject('queueForMails') ->inject('store') ->inject('proofForCode') - ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) { + ->inject('authorization') + ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode, $authorization) use ($createSession) { $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); $proofForToken->setHash(new Sha()); - $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode); + $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode, $authorization); }); App::put('/v1/account/sessions/phone') @@ -2711,6 +2719,7 @@ App::put('/v1/account/sessions/phone') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') + ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2754,7 +2763,8 @@ App::post('/v1/account/tokens/phone') ->inject('plan') ->inject('store') ->inject('proofForCode') - ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2804,9 +2814,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2852,7 +2862,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3243,7 +3253,8 @@ App::patch('/v1/account/email') ->inject('project') ->inject('hooks') ->inject('proofForPassword') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->inject('authorization') + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3295,7 +3306,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3311,7 +3322,7 @@ App::patch('/v1/account/email') $oldTarget = $user->find('identifier', $oldEmail, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); + $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate) { @@ -3352,8 +3363,9 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') - ->action(function (string $phone, string $password, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->inject('proofForPassword') +->inject('authorization') + ->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3368,7 +3380,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3399,7 +3411,7 @@ App::patch('/v1/account/phone') $oldTarget = $user->find('identifier', $oldPhone, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); + $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate $th) { @@ -3535,7 +3547,9 @@ App::post('/v1/account/recovery') ->inject('queueForMails') ->inject('queueForEvents') ->inject('proofForToken') - ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { + if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -3571,7 +3585,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3727,7 +3741,8 @@ App::put('/v1/account/recovery') ->inject('hooks') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { +->inject('authorization') + ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ $profile = $dbForProject->getDocument('users', $userId); @@ -3741,7 +3756,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $newPassword = $proofForPassword->hash($password); @@ -3844,7 +3859,8 @@ App::post('/v1/account/verifications/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('proofForToken') - ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3873,7 +3889,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4072,9 +4088,10 @@ App::put('/v1/account/verifications/email') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForToken') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4086,7 +4103,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -4146,7 +4163,8 @@ App::post('/v1/account/verifications/phone') ->inject('queueForStatsUsage') ->inject('plan') ->inject('proofForCode') - ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -4185,7 +4203,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4291,9 +4309,10 @@ App::put('/v1/account/verifications/phone') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForCode') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4305,7 +4324,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -4358,12 +4377,13 @@ App::post('/v1/account/targets/push') ->inject('dbForProject') ->inject('store') ->inject('proofForToken') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken, Authorization $authorization) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); @@ -4438,9 +4458,10 @@ App::put('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); @@ -4503,8 +4524,9 @@ App::delete('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + ->inject('authorization') + ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index b4f75a9ee5..668bb518fa 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -70,9 +70,9 @@ $avatarCallback = function (string $type, string $code, int $width, int $height, unset($image); }; -$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger) { +$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, ?Logger $logger) { try { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -123,7 +123,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); + $authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -131,7 +131,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); @@ -841,8 +841,9 @@ App::get('/v1/cards/cloud') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + ->inject('authorization') + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) use ($getUserGitHub) { + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -853,7 +854,7 @@ App::get('/v1/cards/cloud') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $authorization, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; @@ -1048,8 +1049,9 @@ App::get('/v1/cards/cloud-back') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + ->inject('authorization') + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) use ($getUserGitHub) { + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1059,7 +1061,7 @@ App::get('/v1/cards/cloud-back') $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $authorization, $logger); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); @@ -1126,8 +1128,9 @@ App::get('/v1/cards/cloud-og') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + ->inject('authorization') + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) use ($getUserGitHub) { + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1142,7 +1145,7 @@ App::get('/v1/cards/cloud-og') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $authorization, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index baf0ba1512..e0cc4181db 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -28,11 +28,12 @@ use Utopia\Validator\Text; App::init() ->groups(['graphql']) ->inject('project') - ->action(function (Document $project) { + ->inject('authorization') + ->action(function (Document $project, Authorization $authorization) { if ( array_key_exists('graphql', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['graphql'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 97ddf8391c..ae3be5f39c 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -120,7 +120,7 @@ App::get('/v1/health/db') $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $database; @@ -131,6 +131,8 @@ App::get('/v1/health/db') } } + // Only throw error if ALL databases failed (no successful pings) + // This allows partial failures in environments where not all DBs are ready if (!empty($failures)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); } @@ -180,7 +182,7 @@ App::get('/v1/health/cache') $output[] = new Document([ 'name' => $key . " ($cache)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $cache; @@ -240,7 +242,7 @@ App::get('/v1/health/pubsub') $output[] = new Document([ 'name' => $key . " ($pubsub)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $pubsub; @@ -822,7 +824,7 @@ App::get('/v1/health/storage/local') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -874,7 +876,7 @@ App::get('/v1/health/storage') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 0b6a314dc5..6ac36fe3c0 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -36,6 +36,7 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -1073,8 +1074,9 @@ App::get('/v1/messaging/providers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1100,7 +1102,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); @@ -2481,8 +2483,9 @@ App::get('/v1/messaging/topics') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2508,7 +2511,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Topic '{$topicId}' for the 'cursor' value not found."); @@ -2782,29 +2785,27 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) { + ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { $subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId; - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); } - - $validator = new Authorization('subscribe'); - - if (!$validator->isValid($topic->getAttribute('subscribe'))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2837,7 +2838,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2882,8 +2883,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2894,7 +2896,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2917,7 +2919,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Subscriber '{$subscriberId}' for the 'cursor' value not found."); @@ -2931,10 +2933,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) { - return function () use ($subscriber, $dbForProject) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $authorization) { + return function () use ($subscriber, $dbForProject, $authorization) { + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); return $subscriber ->setAttribute('target', $target) @@ -3067,9 +3069,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Authorization $authorization, Response $response) { + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3081,8 +3084,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') throw new Exception(Exception::SUBSCRIBER_NOT_FOUND); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber ->setAttribute('target', $target) @@ -3118,9 +3121,10 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3143,7 +3147,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3702,8 +3706,9 @@ App::get('/v1/messaging/messages') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3729,7 +3734,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('messages', $messageId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found."); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 3989ad3298..1a17853577 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -342,6 +342,7 @@ App::post('/v1/migrations/csv/imports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('platform') ->inject('deviceForFiles') @@ -356,6 +357,7 @@ App::post('/v1/migrations/csv/imports') Response $response, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, Document $project, array $platform, Device $deviceForFiles, @@ -363,7 +365,7 @@ App::post('/v1/migrations/csv/imports') Event $queueForEvents, Migration $queueForMigrations ) { - $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -374,7 +376,7 @@ App::post('/v1/migrations/csv/imports') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -491,6 +493,7 @@ App::post('/v1/migrations/csv/exports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('platform') ->inject('queueForEvents') @@ -509,6 +512,7 @@ App::post('/v1/migrations/csv/exports') Response $response, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, Document $project, array $platform, Event $queueForEvents, @@ -520,7 +524,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); + $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -533,12 +537,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $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 = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index a57675d3e8..cda03f923a 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -45,9 +45,10 @@ App::get('/v1/project/usage') ->inject('response') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('getLogsDB') ->inject('smsRates') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) { + ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, Authorization $authorization, callable $getLogsDB, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -102,7 +103,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { + $authorization->skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; @@ -286,7 +287,7 @@ App::get('/v1/project/usage') }, $dbForProject->find('functions')); // This total is includes free and paid SMS usage - $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ + $authPhoneTotal = $authorization->skip(fn () => $dbForProject->sum('stats', 'value', [ Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), @@ -294,7 +295,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ + $authPhoneMetrics = $authorization->skip(fn () => $dbForProject->find('stats', [ Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 1f8555b6cd..aa67a90885 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -86,16 +86,17 @@ App::post('/v1/teams') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($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)), @@ -491,6 +492,7 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -500,9 +502,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('plan') ->inject('proofForPassword') ->inject('proofForToken') - ->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 $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { - $isAppUser = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { + $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -619,13 +621,13 @@ App::post('/v1/teams/:teamId/memberships') ]); try { - $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument)); + $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', $userDocument)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); 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'); @@ -661,11 +663,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { $membership->setAttribute('secret', $proofForToken->hash($secret)); @@ -677,7 +679,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + $authorization->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } else { throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); @@ -863,7 +865,8 @@ App::get('/v1/teams/:teamId/memberships') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -933,7 +936,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1004,7 +1007,8 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); @@ -1024,7 +1028,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1103,8 +1107,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->inject('user') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1121,9 +1126,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($authorization->getRoles()); + $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { // Quick check: fetch up to 2 owners to determine if only one exists @@ -1204,12 +1209,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') ->inject('store') ->inject('proofForToken') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1218,7 +1224,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::MEMBERSHIP_NOT_FOUND); } - $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); @@ -1254,11 +1260,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->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))); // Create session for the user if not logged in if (!$hasSession) { - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1286,7 +1292,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - Authorization::setRole(Role::user($userId)->toString()); + $authorization->addRole(Role::user($userId)->toString()); $encoded = $store ->setProperty('id', $user->getId()) @@ -1324,7 +1330,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1368,8 +1374,9 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('project') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1427,7 +1434,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); } $queueForEvents diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bbe1d8a84a..a963284538 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2678,8 +2678,8 @@ App::get('/v1/users/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('register') - ->action(function (string $range, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -2689,7 +2689,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 4249dbfd48..2270f4fd89 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -76,7 +76,7 @@ use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, array $platform) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Authorization $authorization, Build $queueForBuilds, callable $getProjectDB, Request $request, array $platform) { $errors = []; foreach ($repositories as $repository) { try { @@ -87,12 +87,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); - $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -141,7 +141,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -180,7 +180,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } else { @@ -191,7 +191,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ + $latestComment = $authorization->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -212,7 +212,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -251,7 +251,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -294,7 +294,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -334,7 +334,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); - Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); + $authorization->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); @@ -344,7 +344,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -377,7 +377,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -408,7 +408,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -460,7 +460,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if ($lockAcquired) { // Wrap in try/finally to ensure lock file gets deleted try { - $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : ''; @@ -472,7 +472,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()); } } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -1476,11 +1476,12 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1516,14 +1517,14 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find resourceId from relevant resources table - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push (not committed by us) and not when branch is created or deleted if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1536,16 +1537,16 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - Authorization::skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -1574,12 +1575,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1588,7 +1589,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1599,7 +1600,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1786,17 +1787,18 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = Authorization::skip(fn () => $dbForPlatform->findOne('repositories', [ + $repository = $authorization->skip(fn () => $dbForPlatform->findOne('repositories', [ Query::equal('$id', [$repositoryId]), Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1814,7 +1816,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1846,7 +1848,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerCommitMessage = $pullRequestResponse['title'] ?? ''; $providerCommitUrl = $pullRequestResponse['html_url'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index 23de89af27..ce229ee85f 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -59,7 +59,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -67,16 +67,16 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = Authorization::skip(function () use ($dbForPlatform, $host, $isMd5) { - if ($isMd5) { - return $dbForPlatform->getDocument('rules', md5($host)); - } - - return $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$host]), - ]) ?? new Document(); - }); + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + } else { + $rule = $authorization->skip( + fn () => $dbForPlatform->find('rules', [ + Query::equal('domain', [$host]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } $errorView = __DIR__ . '/../views/general/error.phtml'; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -111,7 +111,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = Authorization::skip( + $project = $authorization->skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -119,7 +119,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -158,7 +158,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw /** @var Document $deployment */ if (!empty($rule->getAttribute('deploymentId', ''))) { - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); } else { // 1.6.x DB schema compatibility // TODO: Make sure deploymentId is never empty, and remove this code @@ -172,15 +172,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // Document of site or function $resource = $resourceType === 'function' ? - Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : - Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId)); + $authorization->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : + $authorization->skip(fn () => $dbForProject->getDocument('sites', $resourceId)); // ID of active deployments // Attempts to use attribute from both schemas (1.6 and 1.7) $activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', '')); // Get deployment document, as intended originally - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -199,8 +199,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $resource = $type === 'function' ? - Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : - Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); + $authorization->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + $authorization->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); @@ -242,7 +242,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $userExists = false; $userId = $payload['userId'] ?? ''; if (!empty($userId)) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -255,7 +255,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); if (!$project->isEmpty() && isset($user)) { $teamId = $project->getAttribute('teamId', ''); $membership = $user->find('teamId', $teamId, 'memberships'); @@ -862,15 +862,16 @@ App::init() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { /* * Appwrite Router */ $hostname = $request->getHostname() ?? ''; $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain - if (!in_array($hostname, $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1141,7 +1142,8 @@ App::options() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { /* * Appwrite Router */ @@ -1182,7 +1184,8 @@ App::error() ->inject('log') ->inject('queueForStatsUsage') ->inject('devKey') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { + ->inject('authorization') + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Document $devKey, Authorization $authorization) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1264,7 +1267,7 @@ App::error() * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { - if (!DBUser::isPrivileged(Authorization::getRoles())) { + if (!DBUser::isPrivileged($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1326,7 +1329,7 @@ App::error() $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', $authorization->getRoles()); $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; if (!empty($sdk)) { @@ -1450,13 +1453,14 @@ App::get('/robots.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1482,13 +1486,14 @@ App::get('/humans.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1572,7 +1577,8 @@ App::get('/v1/ping') ->inject('project') ->inject('dbForPlatform') ->inject('queueForEvents') - ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { + ->inject('authorization') + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1584,7 +1590,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - Authorization::skip(function () use ($dbForPlatform, $project) { + $authorization->skip(function () use ($dbForPlatform, $project) { $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 05c08a2231..23bbb12183 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -30,6 +30,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Queue\Publisher; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; @@ -233,7 +234,8 @@ App::init() ->inject('mode') ->inject('team') ->inject('apiKey') - ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) { $route = $utopia->getRoute(); /** @@ -318,7 +320,7 @@ App::init() // Handle special app role case if ($apiKey->getRole() === User::ROLE_APPS) { // Disable authorization checks for API keys - Authorization::setDefaultStatus(false); + $authorization->setDefaultStatus(false); $user = new User([ '$id' => '', @@ -392,14 +394,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - Authorization::setRole($role); - foreach ($user->getRoles() as $authRole) { - Authorization::setRole($authRole); + $authorization->addRole($role); + foreach ($user->getRoles($authorization) as $authRole) { + $authorization->addRole($authRole); } // Step 6: Update project and user last activity @@ -407,7 +409,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -442,7 +444,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -509,14 +511,15 @@ App::init() ->inject('devKey') ->inject('telemetry') ->inject('platform') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform) use ($usageDatabaseListener, $eventDatabaseListener) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -546,7 +549,7 @@ App::init() $closestLimit = null; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -657,10 +660,10 @@ App::init() if ($useCache) { $route = $utopia->match($request); $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; - $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged(Authorization::getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged($authorization->getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -677,10 +680,10 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -691,8 +694,7 @@ App::init() } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -703,7 +705,7 @@ App::init() if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -714,11 +716,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -814,8 +816,9 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') + ->inject('authorization') ->inject('timelimit') - ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, callable $timelimit) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -976,11 +979,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', 0); $now = DateTime::now(); if ($cacheLog->isEmpty()) { - Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ + $authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -990,7 +993,7 @@ App::shutdown() ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); - Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); + $authorization->skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); // Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load() $cache->save($key, $data['payload']); } @@ -1002,7 +1005,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index efa733fc34..c0f7494125 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -36,7 +36,8 @@ App::init() ->inject('request') ->inject('project') ->inject('geodb') - ->action(function (App $utopia, Request $request, Document $project, Reader $geodb) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) { $denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', ''); if (!empty($denylist && $project->getId() === 'console')) { $countries = explode(',', $denylist); @@ -49,8 +50,8 @@ App::init() $route = $utopia->match($request); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($authorization->getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index b7f857da48..5d08c53eee 100644 --- a/app/http.php +++ b/app/http.php @@ -27,7 +27,6 @@ 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\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Pools\Group; @@ -261,7 +260,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools); // create appwrite database, `dbForPlatform` is a direct access call. - createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) { + createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections, $app) { + $authorization = $app->getResource('authorization'); + if ($dbForPlatform->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) { $adapter = new AdapterDatabase($dbForPlatform); $audit = new Audit($adapter); @@ -321,9 +322,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } - if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + $authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('screenshots'), '$collection' => ID::custom('buckets'), 'name' => 'Screenshots', @@ -338,7 +339,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); Console::info(" └── Creating files collection for screenshots bucket..."); $files = $collections['buckets']['files'] ?? []; @@ -366,7 +367,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + $authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -458,8 +459,12 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool App::setResource('pools', fn () => $pools); try { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); + $authorization = $app->getResource('authorization'); + + $request->setAuthorization($authorization); + $response->setAuthorization($authorization); + $authorization->cleanRoles(); + $authorization->addRole(Role::any()->toString()); $app->run($request, $response); } catch (\Throwable $th) { @@ -501,7 +506,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); $log->addExtra('trace', $th->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []); $sdk = $route->getLabel("sdk", false); @@ -560,7 +565,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { /** @var Utopia\Database\Database $dbForPlatform */ $dbForPlatform = $app->getResource('dbForPlatform'); - Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { + Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) { try { $time = DateTime::now(); $limit = 1000; @@ -577,7 +582,8 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); + $authorization = $app->getResource('authorization'); + $results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries)); } catch (Throwable $th) { Console::error($th->getMessage()); } diff --git a/app/init/database/filters.php b/app/init/database/filters.php index c9ad3fce03..2b2e17b6a9 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -4,7 +4,6 @@ use Appwrite\OpenSSL\OpenSSL; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\System\System; Database::addFilter( @@ -70,11 +69,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $attributes = $database->find('attributes', [ + $attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), - ]); + ])); foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); @@ -105,12 +104,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('indexes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), - ]); + ])); } ); @@ -120,11 +119,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('platforms', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -134,12 +133,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('keys', [ Query::equal('resourceType', ['projects']), Query::equal('resourceInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -149,11 +148,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('devKeys', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -163,11 +162,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('webhooks', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -177,7 +176,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database->find('sessions', [ + return $database->getAuthorization()->skip(fn () => $database->find('sessions', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); @@ -190,7 +189,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -204,7 +203,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('challenges', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -218,7 +217,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('authenticators', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -232,7 +231,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -252,14 +251,14 @@ Database::addFilter( default => ['function', 'site'] }; - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('variables', [ Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', $resourceType), Query::orderAsc('resourceType'), Query::orderAsc(), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -295,11 +294,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('variables', [ Query::equal('resourceType', ['project']), Query::limit(APP_LIMIT_SUBQUERY) - ]); + ])); } ); @@ -332,7 +331,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) @@ -346,7 +345,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $targetIds = Authorization::skip(fn () => \array_map( + $targetIds = $database->getAuthorization()->skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ Query::equal('topicInternalId', [$document->getSequence()]), diff --git a/app/init/resources.php b/app/init/resources.php index d56354c14b..f9a06f7840 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -226,7 +226,7 @@ App::setResource('allowedSchemes', function (Document $project) { /** * Rule associated with a request origin. */ -App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project) { +App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) { $domain = \parse_url($request->getOrigin(), PHP_URL_HOST); if (empty($domain)) { return new Document(); @@ -234,7 +234,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do // TODO: (@Meldiron) Remove after 1.7.x migration $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = Authorization::skip(function () use ($dbForPlatform, $domain, $isMd5) { + $rule = $authorization->skip(function () use ($dbForPlatform, $domain, $isMd5) { if ($isMd5) { return $dbForPlatform->getDocument('rules', md5($domain)); } @@ -249,7 +249,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do } return $rule; -}, ['request', 'dbForPlatform', 'project']); +}, ['request', 'dbForPlatform', 'project', 'authorization']); /** * CORS service @@ -317,7 +317,7 @@ App::setResource('redirectValidator', function (Document $devKey, array $allowed return new Redirect($allowedHostnames, $allowedSchemes); }, ['devKey', 'allowedHostnames', 'allowedSchemes']); -App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) { +App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken, $authorization) { /** * Handles user authentication and session validation. * @@ -337,7 +337,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co * overwriting the previous value. */ - Authorization::setDefaultStatus(true); + $authorization->setDefaultStatus(true); $store->setKey('a_session_' . $project->getId()); @@ -404,7 +404,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co } // if (APP_MODE_ADMIN === $mode) { // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { - // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + // $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. // } else { // $user = new Document([]); // } @@ -436,9 +436,9 @@ App::setResource('user', function (string $mode, Document $project, Document $co $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']); -App::setResource('project', function ($dbForPlatform, $request, $console) { +App::setResource('project', function ($dbForPlatform, $request, $console, $authorization) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ @@ -449,10 +449,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $console; } - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForPlatform', 'request', 'console']); +}, ['dbForPlatform', 'request', 'console', 'authorization']); App::setResource('session', function (User $user, Store $store, Token $proofForToken) { if ($user->isEmpty()) { @@ -475,10 +475,6 @@ App::setResource('session', function (User $user, Store $store, Token $proofForT return; }, ['user', 'store', 'proofForToken']); -App::setResource('console', function () { - return new Document(Config::getParam('console')); -}, []); - App::setResource('store', function (): Store { return new Store(); }); @@ -509,7 +505,15 @@ App::setResource('proofForCode', function (): Code { return $code; }); -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + +App::setResource('authorization', function () { + return new Authorization(); +}, []); + +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -525,6 +529,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -546,13 +551,15 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); + +App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { -App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') @@ -562,12 +569,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $database->setDocumentType('users', User::class); return $database; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); -App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { $databases = []; - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -579,13 +586,15 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $configure = (function (Database $database) use ($project, $dsn) { + $configure = (function (Database $database) use ($project, $dsn, $authorization) { $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - $database->setDocumentType('users', User::class); + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES) + ->setDocumentType('users', User::class) + ; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -615,12 +624,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -App::setResource('getLogsDB', function (Group $pools, Cache $cache) { +App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, &$database) { + return function (?Document $project = null) use ($pools, $cache, $authorization, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int) $project->getSequence()); return $database; @@ -630,6 +639,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -642,7 +652,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); App::setResource('audit', function ($dbForProject) { $adapter = new AdapterDatabase($dbForProject); @@ -841,7 +851,7 @@ App::setResource('promiseAdapter', function ($register) { return $register->get('promiseAdapter'); }, ['register']); -App::setResource('schema', function ($utopia, $dbForProject) { +App::setResource('schema', function ($utopia, $dbForProject, $authorization) { $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); @@ -851,8 +861,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ + $attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) { + $attrs = $authorization->skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -926,7 +936,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { $urls, $params, ); -}, ['utopia', 'dbForProject']); +}, ['utopia', 'dbForProject', 'authorization']); App::setResource('gitHub', function (Cache $cache) { return new VcsGitHub($cache); @@ -954,7 +964,7 @@ App::setResource('smsRates', function () { return []; }); -App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) { +App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform, Authorization $authorization) { $devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', '')); // Check if given key match project's development keys @@ -973,7 +983,7 @@ App::setResource('devKey', function (Request $request, Document $project, array $accessedAt = $key->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DatabaseDateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -990,15 +1000,15 @@ App::setResource('devKey', function (Request $request, Document $project, array /** Update access time as well */ $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $key = $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } return $key; -}, ['request', 'project', 'servers', 'dbForPlatform']); +}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']); -App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request, Authorization $authorization) { $teamInternalId = ''; if ($project->getId() !== 'console') { $teamInternalId = $project->getAttribute('teamInternalId', ''); @@ -1008,7 +1018,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A if (str_starts_with($path, '/v1/projects/:projectId')) { $uri = $request->getURI(); $pid = explode('/', $uri)[3]; - $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); + $p = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); @@ -1017,7 +1027,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -1026,14 +1036,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { + $team = $authorization->skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ Query::equal('$sequence', [$teamInternalId]), ]); }); return $team; -}, ['project', 'dbForPlatform', 'utopia', 'request']); +}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']); App::setResource( 'isResourceBlocked', @@ -1071,7 +1081,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key App::setResource('executor', fn () => new Executor()); -App::setResource('resourceToken', function ($project, $dbForProject, $request) { +App::setResource('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) { $tokenJWT = $request->getParam('token'); if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication @@ -1089,7 +1099,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([]); } - $token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -1107,7 +1117,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { } return match ($token->getAttribute('resourceType')) { - TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { + TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject, $authorization) { $sequences = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); @@ -1118,7 +1128,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { $accessedAt = $token->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) { $token->setAttribute('accessedAt', DatabaseDateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); + $authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ @@ -1133,8 +1143,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { }; } return new Document([]); -}, ['project', 'dbForProject', 'request']); +}, ['project', 'dbForProject', 'request', 'authorization']); -App::setResource('transactionState', function (Database $dbForProject) { - return new TransactionState($dbForProject); -}, ['dbForProject']); +App::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) { + return new TransactionState($dbForProject, $authorization); +}, ['dbForProject', 'authorization']); diff --git a/app/realtime.php b/app/realtime.php index fab0ce7561..31e6015d92 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -32,7 +32,6 @@ 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\DSN\DSN; use Utopia\Logger\Log; use Utopia\Pools\Group; @@ -309,7 +308,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume 'value' => '{}' ]); - $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); + $statsDocument = $database->getAuthorization()->skip(fn () => $database->createDocument('realtime', $document)); break; } catch (Throwable) { Console::warning("Collection not ready. Retrying connection ({$attempts})..."); @@ -339,7 +338,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume ->setAttribute('timestamp', DateTime::now()) ->setAttribute('value', json_encode($payload)); - Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); + $database->getAuthorization()->skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (Throwable $th) { $logError($th, "updateWorkerDocument"); } @@ -370,7 +369,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $payload = []; - $list = Authorization::skip(fn () => $database->find('realtime', [ + $list = $database->getAuthorization()->skip(fn () => $database->find('realtime', [ Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)), ])); @@ -464,13 +463,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, 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 = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); /** @var Appwrite\Utopia\Database\Documents\User $user */ $user = $database->getDocument('users', $userId); - $roles = $user->getRoles(); + $roles = $user->getRoles($database->getAuthorization()); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -526,6 +525,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); + $authorization = $app->getResource('authorization'); /* * Project Check @@ -537,7 +537,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -573,7 +573,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = $user->getRoles(); + $roles = $user->getRoles($authorization); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -586,6 +586,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $realtime->subscribe($project->getId(), $connection, $roles, $channels); + $realtime->connections[$connection]['authorization'] = $authorization; + $user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ @@ -614,6 +616,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $code = 500; } + $message = $th->getMessage(); // sanitize 0 && 5xx errors @@ -643,12 +646,19 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) { try { $response = new Response(new SwooleResponse()); - $projectId = $realtime->connections[$connection]['projectId']; + $projectId = $realtime->connections[$connection]['projectId'] ?? null; + + // Get authorization from connection (stored during onOpen) + $authorization = $realtime->connections[$connection]['authorization'] ?? null; + $database = getConsoleDB(); + $database->setAuthorization($authorization); if ($projectId !== 'console') { - $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $database->getDocument('projects', $projectId)); + $database = getProjectDB($project); + $database->setAuthorization($authorization); } else { $project = null; } @@ -712,10 +722,19 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = $user->getRoles(); + $roles = $user->getRoles($database->getAuthorization()); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); + + // Preserve authorization before subscribe overwrites the connection array + $authorization = $realtime->connections[$connection]['authorization'] ?? null; + $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); + // Restore authorization after subscribe + if ($authorization !== null) { + $realtime->connections[$connection]['authorization'] = $authorization; + } + $user = $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ 'type' => 'response', diff --git a/app/worker.php b/app/worker.php index 7868861cf4..44521fa269 100644 --- a/app/worker.php +++ b/app/worker.php @@ -48,19 +48,30 @@ use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; -Authorization::disable(); Runtime::enableCoroutine(); Server::setResource('register', fn () => $register); -Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { +Server::setResource('authorization', function () { + $authorization = new Authorization(); + $authorization->disable(); + return $authorization; +}, []); + +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, Authorization $authorization) { $pools = $register->get('pools'); $adapter = new DatabasePool($pools->get('console')); $dbForPlatform = new Database($adapter, $cache); - $dbForPlatform->setNamespace('_console'); - $dbForPlatform->setDocumentType('users', User::class); + + $dbForPlatform + ->setAuthorization($authorization) + ->setNamespace('_console') + ->setDocumentType('users', User::class) + ; + + return $dbForPlatform; -}, ['cache', 'register']); +}, ['cache', 'register', 'authorization']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -73,7 +84,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -105,15 +116,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getSequence()); } - $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database + ->setAuthorization($authorization) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform', 'authorization']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -127,7 +140,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - + $database->setAuthorization($authorization); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -164,15 +177,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf ->setNamespace('_' . $project->getSequence()); } - $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database + ->setAuthorization($authorization) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { +Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -182,6 +197,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER) @@ -194,7 +210,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day @@ -509,7 +525,8 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) { + ->inject('authorization') + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, Authorization $authorization) use ($worker, $queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); if ($logger) { @@ -525,7 +542,7 @@ $worker $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', $authorization->getRoles()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/composer.json b/composer.json index 55e4e08402..af63ccd4bd 100644 --- a/composer.json +++ b/composer.json @@ -45,14 +45,14 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.19.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "1.*.*", + "utopia-php/abuse": "1.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "2.0.2-rc3", + "utopia-php/audit": "2.*", "utopia-php/auth": "0.5.*", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", - "utopia-php/config": "1.*.*", - "utopia-php/database": "3.*.*", + "utopia-php/config": "1.*", + "utopia-php/database": "4.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.9.*", "utopia-php/emails": "0.6.*", @@ -64,7 +64,7 @@ "utopia-php/locale": "0.8.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.20.*", - "utopia-php/migration": "1.*.*", + "utopia-php/migration": "1.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 3d263f2d94..66352a66b8 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": "9bac4d8946e35357efa46fd087c9484e", + "content-hash": "2c199847e810b281ec2368c4c93481ea", "packages": [ { "name": "adhocore/jwt", @@ -69,16 +69,16 @@ }, { "name": "appwrite/appwrite", - "version": "19.1.0", + "version": "15.1.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-for-php.git", - "reference": "8738e812062f899c85b2598eef43d6a247f08a56" + "reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/8738e812062f899c85b2598eef43d6a247f08a56", - "reference": "8738e812062f899c85b2598eef43d6a247f08a56", + "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/c438b3885071ac7c0329199dce5e6f6a24dd215b", + "reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b", "shasum": "" }, "require": { @@ -87,7 +87,7 @@ "php": ">=7.1.0" }, "require-dev": { - "mockery/mockery": "^1.6.12", + "mockery/mockery": "^1.6.6", "phpunit/phpunit": "^10" }, "type": "library", @@ -104,10 +104,10 @@ "support": { "email": "team@appwrite.io", "issues": "https://github.com/appwrite/sdk-for-php/issues", - "source": "https://github.com/appwrite/sdk-for-php/tree/19.1.0", + "source": "https://github.com/appwrite/sdk-for-php/tree/15.1.0", "url": "https://appwrite.io/support" }, - "time": "2025-12-18T08:07:43+00:00" + "time": "2025-08-01T04:50:51+00:00" }, { "name": "appwrite/php-clamav", @@ -3455,25 +3455,24 @@ }, { "name": "utopia-php/abuse", - "version": "1.2.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2" + "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/3339d057c6bb1fa3e5ac5b2598923f6938425ec2", - "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", + "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", "shasum": "" }, "require": { - "appwrite/appwrite": "19.*.*", "ext-curl": "*", "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "3.*.*" + "utopia-php/database": "*" }, "require-dev": { "laravel/pint": "1.*", @@ -3501,9 +3500,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/1.2.0" + "source": "https://github.com/utopia-php/abuse/tree/1.0.2" }, - "time": "2026-01-05T21:29:10+00:00" + "time": "2025-10-20T07:18:33+00:00" }, { "name": "utopia-php/analytics", @@ -3553,21 +3552,21 @@ }, { "name": "utopia-php/audit", - "version": "2.0.2-rc3", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "f60a298b516300f56a328403b334b7d62a96e7e7" + "reference": "27d66630f528473cb563bbcf362d7d9a711b384e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7", - "reference": "f60a298b516300f56a328403b334b7d62a96e7e7", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/27d66630f528473cb563bbcf362d7d9a711b384e", + "reference": "27d66630f528473cb563bbcf362d7d9a711b384e", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "3.*", + "utopia-php/database": "4.*", "utopia-php/fetch": "0.5.*", "utopia-php/validators": "0.1.*" }, @@ -3596,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3" + "source": "https://github.com/utopia-php/audit/tree/2.0.2" }, - "time": "2026-01-06T15:32:52+00:00" + "time": "2026-01-07T07:01:25+00:00" }, { "name": "utopia-php/auth", @@ -3899,16 +3898,16 @@ }, { "name": "utopia-php/database", - "version": "3.6.1", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7" + "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", - "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", + "url": "https://api.github.com/repos/utopia-php/database/zipball/fe7a1326ad623609e65587fe8c01a630a7075fee", + "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee", "shasum": "" }, "require": { @@ -3951,9 +3950,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.6.1" + "source": "https://github.com/utopia-php/database/tree/4.3.0" }, - "time": "2025-12-16T09:55:41+00:00" + "time": "2025-11-14T03:43:10+00:00" }, { "name": "utopia-php/detector", @@ -4516,25 +4515,25 @@ }, { "name": "utopia-php/migration", - "version": "1.3.10", + "version": "1.3.5", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "cb357c42a5a5614605b546effbea1204ed64c6b0" + "reference": "6f366f1d4ac2796e59a97d1ba28cedc355e7122e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/cb357c42a5a5614605b546effbea1204ed64c6b0", - "reference": "cb357c42a5a5614605b546effbea1204ed64c6b0", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/6f366f1d4ac2796e59a97d1ba28cedc355e7122e", + "reference": "6f366f1d4ac2796e59a97d1ba28cedc355e7122e", "shasum": "" }, "require": { - "appwrite/appwrite": "19.*", + "appwrite/appwrite": "15.*", "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", "utopia-php/console": "0.0.*", - "utopia-php/database": "3.*", + "utopia-php/database": "4.*", "utopia-php/dsn": "0.2.*", "utopia-php/storage": "0.18.*" }, @@ -4565,9 +4564,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.10" + "source": "https://github.com/utopia-php/migration/tree/1.3.5" }, - "time": "2026-01-06T10:47:11+00:00" + "time": "2025-11-25T11:18:29+00:00" }, { "name": "utopia-php/mongo", @@ -8945,9 +8944,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/audit": 5 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8971,5 +8968,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 23dc6fc2e9..8e098774e6 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -20,10 +20,12 @@ use Utopia\Database\Validator\Authorization; class TransactionState { private Database $dbForProject; - - public function __construct(Database $dbForProject) + private Authorization $authorization; + /** @var Authorization $authorization */ + public function __construct(Database $dbForProject, Authorization $authorization) { $this->dbForProject = $dbForProject; + $this->authorization = $authorization; } @@ -342,12 +344,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + $transaction = $this->authorization->skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') { return []; } - $operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [ + $operations = $this->authorization->skip(fn () => $this->dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index bc37924db6..ea51225ba6 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -100,8 +100,6 @@ abstract class Migration public function __construct() { - Authorization::disable(); - Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -129,6 +127,7 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -136,6 +135,9 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; + $authorization->disable(); + $authorization->setDefaultStatus(false); + return $this; } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 47afc90986..33b69dd589 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -13,6 +13,7 @@ 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\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; @@ -142,7 +143,7 @@ class Base extends Action return $deployment; } - public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document + public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = ''): Document { $deploymentId = ID::unique(); $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); @@ -239,7 +240,7 @@ class Base extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -265,7 +266,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -302,7 +303,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -328,6 +329,8 @@ class Base extends Action } } + $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) @@ -336,4 +339,34 @@ class Base extends Action return $deployment; } + + /** + * Update empty manual rule for deployment. + * In case of first deployment, deployment ID will be empty in the rules, so we need to update it here. + * + * @param \Utopia\Database\Document $project + * @param \Utopia\Database\Document $resource + * @param \Utopia\Database\Document $deployment + * @param \Utopia\Database\Database $dbForPlatform + * @return void + */ + public static function updateEmptyManualRule(Document $project, Document $resource, Document $deployment, Database $dbForPlatform, Authorization $authorization) + { + $resourceType = $resource->getCollection() === 'sites' ? 'site' : 'function'; + + $queries = [ + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), + Query::equal('deploymentResourceType', [$resourceType]), + Query::equal('deploymentId', ['']), + Query::equal('type', ['deployment']), + Query::equal('trigger', ['manual']), + ]; + $dbForPlatform->forEach('rules', function (Document $rule) use ($deployment, $dbForPlatform, $authorization) { + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([ + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getSequence(), + ]))); + }, $queries); + } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index aa43b12125..1468bf71ac 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -60,6 +60,7 @@ class Get extends Action ->inject('response') ->inject('dbForPlatform') ->inject('platform') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,7 +69,8 @@ class Get extends Action string $type, Response $response, Database $dbForPlatform, - array $platform + array $platform, + Authorization $authorization, ) { $domains = $platform['hostnames'] ?? []; if ($type === 'rules') { @@ -121,7 +123,7 @@ class Get extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $document = $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$value]), ])); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 83a401a35e..e2df5d92e6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -292,7 +292,7 @@ abstract class Action extends UtopiaAction }; } - protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document + protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): Document { $key = $attribute->getAttribute('key'); $type = $attribute->getAttribute('type', ''); @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException(), params: [$type]); } - $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, params: [$databaseId]); @@ -371,7 +371,7 @@ abstract class Action extends UtopiaAction \in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) && $attribute->getAttribute('required') ) { - $hasData = !Authorization::skip(fn () => $dbForProject + $hasData = !$authorization->skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -472,9 +472,9 @@ abstract class Action extends UtopiaAction return $attribute; } - protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document + protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index f04532aeee..442461fdd3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -81,7 +83,7 @@ class Create extends Action 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 003b4227c9..92324aae70 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -68,10 +69,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -79,6 +81,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_BOOLEAN, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index c2982445a4..bd3108a871 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index 984d4b0245..2518875424 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_DATETIME, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 649cde10aa..37ae2a7bfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -67,12 +67,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index b36072eb75..a36e264e50 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 382f16b469..609a337625 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_EMAIL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 9145191b0c..3c47d1fdfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -73,10 +74,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { if (!is_null($default) && !\in_array($default, $elements, true)) { throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); @@ -98,7 +100,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 2f47eb0cc6..5bea5230c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_ENUM, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 56d8874794..0dc11bd76c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,10 +75,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $min ??= -PHP_FLOAT_MAX; $max ??= PHP_FLOAT_MAX; @@ -100,7 +102,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 330c649f27..20b5c0767d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_FLOAT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 3a8eece531..436b22c6c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -68,12 +68,13 @@ class Get extends Action ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 2340d1d55d..2adf3977f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index 236dbf7f83..eccf18b005 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_IP, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 30f58097ce..58ded9b78a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,10 +75,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $min ??= \PHP_INT_MIN; $max ??= \PHP_INT_MAX; @@ -102,7 +104,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 67c371c69d..84a43018d1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_INTEGER, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index f0fd728902..fc846957b0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_LINESTRING, 'required' => $required, 'default' => $default - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 3407da2b34..8fff545921 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_LINESTRING, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index f2e4d19267..a89c21581d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POINT, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index 86e78e56e3..9561fe6b96 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_POINT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 4c49b21050..54da3ac604 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POLYGON, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index 0dbb117cec..b82a3d4be0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_POLYGON, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index b43568a968..615e64dfd7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -83,16 +83,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $key ??= $relatedCollectionId; $twoWayKeyWasProvided = $twoWayKey !== null; $twoWayKey ??= $collectionId; - $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, params: [$databaseId]); } @@ -154,7 +155,7 @@ class Create extends Action 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, ] - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); foreach ($attribute->getAttribute('options', []) as $k => $option) { $attribute->setAttribute($k, $option); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index feed58a4ff..d180131a44 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,6 +72,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -82,7 +84,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -90,6 +93,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_RELATIONSHIP, required: false, options: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index b42558f063..b3fe03cace 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -77,6 +78,7 @@ class Create extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -93,7 +95,8 @@ class Create extends Action Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, - array $plan + array $plan, + Authorization $authorization ): void { if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.'); @@ -132,7 +135,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $attribute->setAttribute('encrypt', $encrypt); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 53ea2a0e03..37547f3da8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,6 +73,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -85,7 +87,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -93,6 +96,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, size: $size, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index 7529845016..ed1a23acf5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,6 +71,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -83,7 +85,8 @@ class Create extends Action UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -93,7 +96,7 @@ class Create extends Action 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 9ba8ebb859..08f7a26fd9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,6 +70,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -81,7 +83,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( $databaseId, @@ -89,6 +92,7 @@ class Update extends Action $key, $dbForProject, $queueForEvents, + $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_URL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 6bfe5f8913..61c5b295cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -64,12 +64,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 724f40f00e..89cc14056a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -85,12 +85,13 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index af36649061..fd2c419954 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -64,12 +64,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index f16d00998d..ec65135a05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -258,9 +258,9 @@ abstract class Action extends DatabasesAction Document $collection, Document $document, Database $dbForProject, - /* options */ array &$collectionsCache, + Authorization $authorization, ?int &$operations = null, ): bool { @@ -297,7 +297,7 @@ abstract class Action extends DatabasesAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = Authorization::skip( + $relatedCollectionDoc = $authorization->skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId @@ -323,7 +323,8 @@ abstract class Action extends DatabasesAction document: $relation, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations + operations: $operations, + authorization: $authorization ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 53831f0fc5..16b7bd1b25 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -85,20 +85,21 @@ class Decrement extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $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, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -106,7 +107,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index ea680db3b1..7adae7633b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -85,20 +85,21 @@ class Increment extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $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, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -106,7 +107,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6ec06f5c8a..bbc63da499 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -24,6 +24,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -132,9 +133,10 @@ class Create extends Action ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void { $data = \is_string($data) ? \json_decode($data, true) @@ -178,19 +180,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -204,7 +206,7 @@ class Create extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext()); } - $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, @@ -247,8 +249,8 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + if (!$authorization->hasRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')'); } } } @@ -259,21 +261,25 @@ class Create extends Action $operations = 0; - $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations) { + $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations, $authorization) { $operations++; $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validator = new Authorization($permission); - $valid = $validator->isValid($collection->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + $validCollection = $authorization->isValid( + new Input($permission, $collection->getPermissionsByType($permission)) + ); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($document->getUpdate()); + $validDocument = $authorization->isValid( + new Input($permission, $document->getUpdate()) + ); + $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } } @@ -298,7 +304,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -314,7 +320,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = Authorization::skip( + $current = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -369,7 +375,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -468,6 +474,7 @@ class Create extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index faae638c88..7acf8e386e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -83,6 +83,7 @@ class Delete extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,18 +98,19 @@ class Delete extends Action Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, - array $plan + array $plan, + Authorization $authorization ): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -121,7 +123,7 @@ class Delete extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -131,7 +133,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -205,6 +207,7 @@ class Delete extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index f560267d4b..cb8b0dd42e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -70,20 +70,21 @@ class Get extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -125,6 +126,7 @@ class Get extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization, operations: $operations ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index a4dd38ef67..2f5579f0ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -72,13 +72,14 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 707857347a..a92d8ec180 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -87,10 +87,11 @@ class Update extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -98,16 +99,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -125,7 +126,7 @@ class Update extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -140,7 +141,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -153,7 +154,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -171,7 +172,7 @@ class Update extends Action $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { $operations++; $relationships = \array_filter( @@ -195,7 +196,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -212,7 +213,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -249,7 +250,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -340,6 +341,7 @@ class Update extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization, ); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index b32871add2..62e59dd010 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -91,10 +91,11 @@ class Upsert extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -106,15 +107,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -139,7 +140,7 @@ class Upsert extends Action // Use transaction-aware document retrieval to see changes from same transaction $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -155,7 +156,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -168,7 +169,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -181,7 +182,7 @@ class Upsert extends Action $newDocument = new Document($data); $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { $operations++; $relationships = \array_filter( @@ -205,7 +206,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -222,7 +223,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -259,7 +260,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -361,6 +362,7 @@ class Upsert extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); $relationships = \array_map( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 8b770284c3..ff94e67b02 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -74,20 +74,21 @@ class XList extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -115,7 +116,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); @@ -161,7 +162,8 @@ class XList extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations, + authorization: $authorization, + operations: $operations ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index e7909772a5..d8df8f1f8c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -57,12 +57,13 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 872b7348fe..5b035a8688 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -79,12 +79,13 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 27b28e866c..d9f9f66504 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -70,12 +70,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index d66bf8f38f..661f259910 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -59,12 +59,13 @@ class Get extends Action ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index abbdefb4d5..90826ffbe3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -66,13 +66,14 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { /** @var Document $database */ - $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, params: [$databaseId]); @@ -112,7 +113,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = $authorization->skip(fn () => $dbForProject->find('indexes', [ Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 0f5a57c6e9..0b6e47a798 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -71,13 +71,14 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void { - $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, params: [$databaseId]); @@ -112,9 +113,9 @@ class XList extends Action $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); + $os = $detector->getOS() ?: []; + $client = $detector->getClient() ?: []; + $device = $detector->getDevice() ?: []; $output[$i] = new Document([ 'event' => $log['event'], @@ -122,20 +123,20 @@ class XList extends Action 'userEmail' => $log['data']['userEmail'] ?? null, 'userName' => $log['data']['userName'] ?? null, 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'ip' => $log['ip'] ?? null, + 'time' => $log['time'] ?? null, + 'osCode' => $os['osCode'] ?? null, + 'osName' => $os['osName'] ?? null, + 'osVersion' => $os['osVersion'] ?? null, + 'clientType' => $client['clientType'] ?? null, + 'clientCode' => $client['clientCode'] ?? null, + 'clientName' => $client['clientName'] ?? null, + 'clientVersion' => $client['clientVersion'] ?? null, + 'clientEngine' => $client['clientEngine'] ?? null, + 'clientEngineVersion' => $client['clientEngineVersion'] ?? null, + 'deviceName' => $device['deviceName'] ?? null, + 'deviceBrand' => $device['deviceBrand'] ?? null, + 'deviceModel' => $device['deviceModel'] ?? null ]); $record = $geodb->get($log['ip']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index e319a33e67..304ce5c88e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -71,12 +71,13 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index c4a46650c9..0552a31509 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -63,10 +63,11 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); @@ -83,7 +84,7 @@ class Get extends Action str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index b0b0385bf5..c23286f3cd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -67,12 +67,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php index 20c71223c6..4ca20f8414 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -55,10 +55,11 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('authorization') ->callback($this->action(...)); } - public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user): void + public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, Authorization $authorization): void { $permissions = []; if (!empty($user->getId())) { @@ -73,7 +74,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ + $transaction = $authorization->skip(fn () => $dbForProject->createDocument('transactions', new Document([ '$id' => ID::unique(), '$permissions' => $permissions, 'status' => 'pending', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php index 5a2568db0c..f09ed2bc27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -18,6 +18,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -63,21 +64,22 @@ class Create extends Action ->inject('dbForProject') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan): void + public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization): void { if (empty($operations)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -113,13 +115,13 @@ class Create extends Action throw new Exception(Exception::USER_UNAUTHORIZED); } - $database = $databases[$operation['databaseId']] ??= Authorization::skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); + $database = $databases[$operation['databaseId']] ??= $authorization->skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$operation['databaseId']]); } $collection = $collections[$operation[$this->getGroupId()]] ??= - Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND, params: [$operation[$this->getGroupId()]]); @@ -165,14 +167,20 @@ class Create extends Action // For individual operations, enforce permissions unless using API key/admin if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validator = new Authorization($permissionType); - $collectionValid = $validator->isValid($collection->getPermissionsByType($permissionType)); + + $collectionValid = $authorization->isValid( + new Input($permissionType, $collection->getPermissionsByType($permissionType)) + ); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $validator->isValid($document->getUpdate()); + $documentValid = $authorization->isValid( + new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) + ); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $validator->isValid($document->getDelete()); + $documentValid = $authorization->isValid( + new Input(Database::PERMISSION_DELETE, $document->getDelete()) + ); } } @@ -189,7 +197,7 @@ class Create extends Action // Users can only set permissions for roles they have if (isset($operation['data']['$permissions'])) { $permissions = $operation['data']['$permissions']; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -201,7 +209,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -230,7 +238,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { $dbForProject->createDocuments('transactionLogs', $staged); return $dbForProject->increaseDocumentAttribute( 'transactions', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php index 9235c81b8e..e4f1051464 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -76,6 +76,7 @@ class Update extends Action ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('authorization') ->callback($this->action(...)); } @@ -102,7 +103,7 @@ class Update extends Action * @throws Structure * @throws \Utopia\Exception */ - public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void + public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization): void { if (!$commit && !$rollback) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); @@ -111,11 +112,11 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -138,12 +139,12 @@ class Update extends Action $currentDocumentId = null; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) { + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -167,7 +168,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = Authorization::skip( + $collections[$collectionId] = $authorization->skip( fn () => $dbForProject->getCollection($collectionId) ); } @@ -232,7 +233,7 @@ class Update extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -243,33 +244,33 @@ class Update extends Action ->setDocument($transaction); }); } catch (NotFoundException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e, params: [$currentDocumentId ?? 'unknown']); } catch (DuplicateException | ConflictException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_CONFLICT, previous: $e); } catch (StructureException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (LimitException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, $e->getMessage()); } catch (TransactionException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_FAILED, $e->getMessage()); } catch (QueryException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); @@ -297,11 +298,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ + $database = $authorization->skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = $authorization->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -393,7 +394,7 @@ class Update extends Action } if ($rollback) { - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'failed']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index a717b00ae4..a1aa7a70b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -59,10 +59,11 @@ class Get extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); @@ -81,7 +82,7 @@ class Get extends Action str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index c13149cfc7..757f845c68 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -56,10 +56,11 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, UtopiaResponse $response, Database $dbForProject): void + public function action(string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $periods = Config::getParam('usage', []); @@ -74,7 +75,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php index c0d502d10a..eede1b221b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php @@ -60,6 +60,7 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php index c5939b6974..cd8d392cfc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php @@ -61,6 +61,7 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php index 63693abb67..79722efee1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php @@ -62,6 +62,7 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php index b022d0ed85..c39681a743 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php @@ -63,6 +63,7 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php index 8a691a6e98..da63b0cef7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php @@ -58,6 +58,7 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php index 6d19f99b7b..51e7f295a1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php @@ -61,6 +61,7 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php index 48a04304bd..daca13d587 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php @@ -62,6 +62,7 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php index bd280a2910..4d5881c81e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php @@ -64,6 +64,7 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php index ac5c1cf907..122671adc5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php @@ -65,6 +65,7 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php index 8293d66992..cd898fa0bf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php @@ -63,6 +63,7 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php index bf2815db45..ee9c5f6cb1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php @@ -64,6 +64,7 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php index ee88ac8683..39dafbd1a6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php @@ -61,6 +61,7 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php index 9b38cd9dfd..80c764b4c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php @@ -61,6 +61,7 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php index 7db8625ebf..54ed029c71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php @@ -62,6 +62,7 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index e0ed059681..45e0cc6f60 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -63,6 +63,7 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index 7afc239201..f1f4ebb4a9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -64,6 +64,7 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php index 6110d6ee07..227fece7de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php @@ -61,6 +61,7 @@ class Create extends LineCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php index afd0098152..b0e433da5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php @@ -63,6 +63,7 @@ class Update extends LineUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php index 084adca860..3fc5865905 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php @@ -61,6 +61,7 @@ class Create extends PointCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 632be85871..040b8171d7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php @@ -63,6 +63,7 @@ class Update extends PointUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php index 723940af58..630340ba7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php @@ -61,6 +61,7 @@ class Create extends PolygonCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 91b55f74b4..43b4a4e6a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php @@ -63,6 +63,7 @@ class Update extends PolygonUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php index f3933160c0..7f28a3cdb7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php @@ -73,6 +73,7 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index eb87713457..fd7fdab8de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php @@ -65,6 +65,7 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php index 9279409e88..ff50313a7c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php @@ -66,6 +66,7 @@ class Create extends StringCreate ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 9fffa71b33..6ad1be124b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php @@ -65,6 +65,7 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php index 50f5ea5d5b..b19d6e80a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php @@ -61,6 +61,7 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index b52ea66ce1..dce11964e8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php @@ -62,6 +62,7 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 39551e5113..13ebe14682 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -52,6 +52,7 @@ class XList extends AttributesXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php index 7287c2cb3e..bd08ad5617 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -67,6 +67,7 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php index d4af8b3508..925a7b2494 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php @@ -55,6 +55,7 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php index 4286ee07ca..ad83291815 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php @@ -50,6 +50,7 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index 727334b6da..09720f4d71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php @@ -66,6 +66,8 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } + } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php index 7d187ab5a1..7fa8073d1e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php @@ -61,6 +61,7 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php index 75ee507aa8..246d569825 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php @@ -52,6 +52,7 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index bf5f27e388..1dc2d3ea43 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -54,6 +54,7 @@ class XList extends IndexXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php index 5eab050b7e..79691436e4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php @@ -50,6 +50,7 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php index accb0392fe..b9896d282d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php @@ -66,6 +66,7 @@ class Delete extends DocumentsDelete ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php index fea59b8b13..f4ccea1698 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php @@ -68,6 +68,7 @@ class Update extends DocumentsUpdate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php index 492af25e9f..69a687d92f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php @@ -68,6 +68,7 @@ class Upsert extends DocumentsUpsert ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php index 42f2919ce1..a660b008e1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php @@ -67,6 +67,7 @@ class Decrement extends DecrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php index 3d04d71c26..c2b69429ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php @@ -67,6 +67,7 @@ class Increment extends IncrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php index b5491a593b..c70ed71378 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php @@ -111,6 +111,7 @@ class Create extends DocumentCreate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php index bcd8682a48..1763491c19 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php @@ -70,6 +70,7 @@ class Delete extends DocumentDelete ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php index 450fb4d746..bb24e93de0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php @@ -58,6 +58,7 @@ class Get extends DocumentGet ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php index 27bd82195d..86bfcfec85 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php @@ -51,6 +51,7 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php index fe4ffc4995..0879055a78 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php @@ -69,6 +69,7 @@ class Update extends DocumentUpdate ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index 0fbaa921cb..99e0487c93 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -72,6 +72,7 @@ class Upsert extends DocumentUpsert ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index c51017fa75..230d391110 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -59,6 +59,7 @@ class XList extends DocumentXList ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php index 03316783cd..0d3bc9afc1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -62,6 +62,7 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php index 0fb44ee94a..b8be7edd56 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php @@ -52,6 +52,7 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index e0c590379b..5532203d0a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -55,6 +55,7 @@ class XList extends CollectionXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php index 27454664f4..e7e5f0132f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php @@ -50,6 +50,7 @@ class Create extends TransactionsCreate ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php index 4668ae2d15..1228c83e30 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php @@ -54,6 +54,7 @@ class Create extends OperationsCreate ->inject('dbForProject') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php index 4337a8d28d..8be28ce9f7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php @@ -60,6 +60,7 @@ class Update extends TransactionsUpdate ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php index 89b9fbd8c2..87be8a9eab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php @@ -48,6 +48,7 @@ class Get extends DatabaseUsageGet ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php index 0bd96fc40a..2cde337f5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php @@ -46,6 +46,7 @@ class XList extends DatabaseUsageXList ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index e7e34d4c5b..c5ae08728d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -17,6 +17,7 @@ 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\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -88,6 +89,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -105,7 +107,8 @@ class Create extends Action Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index 0aaea3bd4a..acfaa965ac 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -15,6 +15,7 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -77,6 +78,7 @@ class Create extends Base ->inject('project') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -95,7 +97,8 @@ class Create extends Base Event $queueForEvents, Document $project, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -127,7 +130,9 @@ class Create extends Base queueForBuilds: $queueForBuilds, template: $template, github: $github, - activate: $activate + activate: $activate, + referenceType: $type, + reference: $reference ); $queueForEvents @@ -170,6 +175,9 @@ class Create extends Base ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); + + $this->updateEmptyManualRule($project, $function, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php index 69594c3d86..25dce63b38 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -87,7 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, ) { $function = $dbForProject->getDocument('functions', $functionId); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 81f55ba829..1a265298d3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -29,6 +29,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -99,6 +100,7 @@ class Create extends Base ->inject('proofForToken') ->inject('executor') ->inject('platform') + ->inject('authorization') ->callback($this->action(...)); } @@ -123,7 +125,8 @@ class Create extends Base Store $store, Token $proofForToken, Executor $executor, - array $platform + array $platform, + Authorization $authorization, ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -161,10 +164,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -180,7 +183,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); @@ -194,10 +197,8 @@ class Create extends Base throw new Exception(Exception::BUILD_NOT_READY); } - $validator = new Authorization('execute'); - - if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + if (!$authorization->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $jwt = ''; // initialize @@ -295,7 +296,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -336,7 +337,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -488,7 +489,7 @@ class Create extends Base ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index 9a93e5a342..c7a9a6d330 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -61,6 +61,7 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Delete extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -108,7 +110,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 6bd0a3675e..c5eebe139e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -52,6 +52,7 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -59,12 +60,13 @@ class Get extends Base string $functionId, string $executionId, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 20680e87ff..ff381e1f3d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -60,6 +60,7 @@ class XList extends Base ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,12 +69,13 @@ class XList extends Base array $queries, bool $includeTotal, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index 5c226c5925..6ad488283e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -115,6 +115,7 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -152,7 +153,8 @@ class Create extends Base Func $queueForFunctions, Database $dbForPlatform, Request $request, - GitHub $github + GitHub $github, + Authorization $authorization ) { // Temporary abuse check @@ -237,7 +239,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = Authorization::skip( + $schedule = $authorization->skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -315,6 +317,7 @@ class Create extends Base template: $template, github: $github, activate: true, + authorization: $authorization, reference: $providerBranch, referenceType: 'branch' ); @@ -366,7 +369,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $rule = Authorization::skip( + $rule = $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index dfa6636554..9cafc17bbe 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -61,6 +61,7 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Delete extends Base Database $dbForProject, DeleteEvent $queueForDeletes, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -87,7 +89,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index b6dcfd6cf8..aeccf98a02 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -62,6 +62,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,7 +73,8 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -101,7 +103,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -112,12 +114,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index adb29bc533..55c5b30418 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -104,6 +104,7 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') + ->inject('authorization') ->callback($this->action(...)); } @@ -134,7 +135,8 @@ class Update extends Base Build $queueForBuilds, Database $dbForPlatform, GitHub $github, - Executor $executor + Executor $executor, + Authorization $authorization ) { // TODO: If only branch changes, re-deploy $function = $dbForProject->getDocument('functions', $functionId); @@ -282,7 +284,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents->setParam('functionId', $function->getId()); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index acb6995d6f..1fa65d0cc9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -55,10 +55,11 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $functionId, string $range, Response $response, Database $dbForProject) + public function action(string $functionId, string $range, Response $response, Database $dbForProject, Authorization $authorization) { $function = $dbForProject->getDocument('functions', $functionId); @@ -83,7 +84,7 @@ class Get extends Base str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index 6a4ded4db7..38a95d4469 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -52,10 +52,11 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -75,7 +76,7 @@ class XList extends Base str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 815f1bd8fc..5438479d40 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -65,6 +65,7 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -76,7 +77,8 @@ class Create extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Document $project + Document $project, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -119,7 +121,7 @@ class Create extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 50c1de4232..161eed3112 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -57,6 +57,7 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -65,7 +66,8 @@ class Delete extends Base string $variableId, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -92,7 +94,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 5c1f5809cd..6af5ac90c2 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -62,6 +62,7 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -73,7 +74,8 @@ class Update extends Base ?bool $secret, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -110,7 +112,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index e38a56bd2b..d8bfb79417 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -27,7 +27,6 @@ use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Detector\Detection\Rendering\SSR; use Utopia\Detector\Detection\Rendering\XStatic; use Utopia\Detector\Detector\Rendering; @@ -928,11 +927,11 @@ class Builds extends Action ->trigger(); try { - $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $rule = $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal('deploymentInternalId', [$deployment->getSequence()]), - ])); + ]); if ($rule->isEmpty()) { throw new \Exception("Rule for build not found"); @@ -942,7 +941,7 @@ class Builds extends Action $client->setTimeout(\intval($resource->getAttribute('timeout', '15')) * 1000); $client->addHeader('content-type', FetchClient::CONTENT_TYPE_APPLICATION_JSON); - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); $configs = [ 'screenshotLight' => [ @@ -1064,7 +1063,7 @@ class Builds extends Action 'metadata' => ['content_type' => $mimeType], ]); - Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); + $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file); $deployment->setAttribute($key, $fileId); } @@ -1288,7 +1287,7 @@ class Builds extends Action ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $resource->getAttribute('schedule')) ->setAttribute('active', !empty($resource->getAttribute('schedule')) && !empty($resource->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } Console::info('Deployment action finished'); @@ -1497,7 +1496,6 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception - * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1586,11 +1584,11 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $rule = $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal("deploymentInternalId", [$deployment->getSequence()]), - ])); + ]); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $previewUrl = match($resource->getCollection()) { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 4ba51bca37..3de0322d6e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -87,6 +87,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -106,7 +107,8 @@ class Create extends Action Device $deviceForSites, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -276,7 +278,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -341,7 +343,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -366,6 +368,8 @@ class Create extends Action } } + + $metadata = null; $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 2f9b1bdfde..9554e2aa14 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -65,6 +65,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') + ->inject('authorization') ->callback($this->action(...)); } @@ -78,7 +79,8 @@ class Create extends Action Database $dbForPlatform, Event $queueForEvents, Build $queueForBuilds, - Device $deviceForSites + Device $deviceForSites, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -147,7 +149,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 5f1d446809..30d5e779c1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -79,6 +79,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,7 +98,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -130,6 +132,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, ); $queueForEvents @@ -189,7 +192,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -209,6 +212,8 @@ class Create extends Base ])) ); + $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index 915e3c5c9f..feff28427e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -72,6 +73,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -87,7 +89,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -110,6 +113,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, reference: $reference, referenceType: $type ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index f962d0118d..b5d956128b 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -60,6 +60,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -104,12 +106,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index af96c10457..5c274d6a20 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -55,6 +55,7 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -62,7 +63,8 @@ class Get extends Base string $siteId, string $range, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -91,7 +93,7 @@ class Get extends Base ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index d36cc56ae5..a90cb0cab9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -52,10 +52,11 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -78,7 +79,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index f79dece530..5f1bd55788 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -6,32 +6,31 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Documents\User; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; class Action extends UtopiaAction { - protected function getFileAndBucket(Database $dbForProject, string $bucketId, string $fileId): array + protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, string $bucketId, string $fileId): array { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); - if (!$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 3d1f6eef38..6cbaeaa915 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -14,6 +14,7 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -65,23 +66,23 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { /** * @var Document $bucket * @var Document $file */ - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $bucketPermission = $validator->isValid($bucket->getUpdate()); + $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if ($fileSecurity) { - $filePermission = $validator->isValid($file->getUpdate()); + $filePermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); if (!$bucketPermission && !$filePermission) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 8a9301713b..13da92cbc6 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -13,6 +13,7 @@ use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; @@ -57,12 +58,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) + public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization) { - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 3e35c1c1fa..cc6981fa1b 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -31,6 +31,7 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') + ->inject('authorisation') ->callback($this->action(...)); } @@ -47,8 +48,8 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, + Authorization $authorization ): void { - Authorization::disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); @@ -66,14 +67,14 @@ class Migrate extends Action $count = 0; $total = $dbForPlatform->count('projects') + 1; - $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total, $authorization) { /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); $dbForProject->disableValidation(); try { $migration - ->setProject($project, $dbForProject, $dbForPlatform, $getProjectDB) + ->setProject($project, $dbForProject, $dbForPlatform, $authorization, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -88,7 +89,7 @@ class Migrate extends Action try { $migration - ->setProject($console, $getProjectDB($console), $dbForPlatform, $getProjectDB) + ->setProject($console, $getProjectDB($console), $dbForPlatform, $authorization, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 9698fe9034..19ed3bc099 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -8,7 +8,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; @@ -61,7 +60,7 @@ abstract class ScheduleBase extends Action $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $dbForPlatform->updateDocument('projects', $project->getId(), $project); } } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index b64dd61f86..6d04d2109a 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -8,7 +8,6 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\System\System; /** @@ -61,9 +60,7 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue) { - Authorization::disable(); - Authorization::setDefaultStatus(false); + Console::loop(function () use ($queue, $dbForPlatform) { $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); /** diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index be81bd888f..3e49ca3799 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -19,12 +19,10 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; -use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -203,7 +201,6 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void - * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -1002,14 +999,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); if ($bucket->isEmpty()) { Console::error('Failed to get bucket for deployment screenshots'); return; } foreach ($screenshotIds as $id) { - $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); + $file = $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index fba5154079..a54b982634 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -15,7 +15,6 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; @@ -337,7 +336,6 @@ class Functions extends Action * @param string|null $eventData * @param string|null $executionId * @return void - * @throws Authorization * @throws Structure * @throws \Utopia\Database\Exception * @throws Conflict diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 972757408e..7c4efc6234 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -80,6 +80,7 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,6 +98,7 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, + Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -126,7 +128,13 @@ class Migrations extends Action } try { - $this->processMigration($migration, $queueForRealtime, $queueForMails, $platform); + $this->processMigration( + $migration, + $queueForRealtime, + $queueForMails, + $platform, + $authorization + ); } finally { $this->dbForProject = null; $this->dbForPlatform = null; @@ -137,7 +145,7 @@ class Migrations extends Action $this->plan = []; $this->sourceReport = []; - gc_collect_cycles(); + \gc_collect_cycles(); } } @@ -311,6 +319,7 @@ class Migrations extends Action Realtime $queueForRealtime, Mail $queueForMails, array $platform, + Authorization $authorization, ): void { $project = $this->dbForPlatform->getDocument('projects', $this->project->getId()); $tempAPIKey = $this->generateAPIKey($project); @@ -435,7 +444,7 @@ class Migrations extends Action $source?->success(); if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization); } } @@ -463,6 +472,7 @@ class Migrations extends Action Mail $queueForMails, Realtime $queueForRealtime, array $platform, + Authorization $authorization, ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -476,7 +486,7 @@ class Migrations extends Action throw new \Exception('User ' . $userInternalId . ' not found'); } - $bucket = Authorization::skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new \Exception('Bucket not found'); } diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index a85b0a897c..cbd22aaee5 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -7,7 +7,6 @@ use Utopia\Auth\Proofs\Token; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; class User extends Document @@ -36,11 +35,11 @@ class User extends Document * * @return array */ - public function getRoles(): array + public function getRoles($authorization): array { $roles = []; - if (!$this->isPrivileged(Authorization::getRoles()) && !$this->isApp(Authorization::getRoles())) { + if (!$this->isPrivileged($authorization->getRoles()) && !$this->isApp($authorization->getRoles())) { if ($this->getId()) { $roles[] = Role::user($this->getId())->toString(); $roles[] = Role::users()->toString(); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index cb449e6ffa..c87279f126 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -214,7 +214,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isAppUser = User::isApp($roles); if ($isAppUser) { @@ -237,4 +237,11 @@ class Request extends UtopiaRequest ksort($params); return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } + + private ?Authorization $authorization = null; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 56fed746d9..6d47d4d150 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -10,7 +10,7 @@ abstract class Filter private array $params; private ?Database $dbForProject; - public function __construct(Database $dbForProject = null, array $params = []) + public function __construct(?Database $dbForProject = null, array $params = []) { $this->params = $params; $this->dbForProject = $dbForProject; diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 69e7da6b7a..e3d5fe2f79 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -7,7 +7,6 @@ use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; class V20 extends Filter { @@ -138,7 +137,7 @@ class V20 extends Filter } try { - $database = Authorization::skip(fn () => $dbForProject->getDocument( + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'databases', $databaseId )); @@ -150,7 +149,7 @@ class V20 extends Filter } try { - $collection = Authorization::skip(fn () => $dbForProject->getDocument( + $collection = $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId )); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 1dfaa1a41f..f2ac486f82 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -483,7 +483,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isPrivilegedUser = DBUser::isPrivileged($roles); $isAppUser = DBUser::isApp($roles); @@ -651,4 +651,11 @@ class Response extends SwooleResponse self::$showSensitive = false; } } + + private ?Authorization $authorization = null; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index 6496aa285a..0c9854160e 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,19 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + + return $this->authorization; + } + public function createCollection(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ @@ -111,8 +124,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -134,7 +147,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +158,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -222,7 +235,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index 2f69c037d0..84cb4bce3a 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,19 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + + public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ @@ -111,8 +124,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicRows = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -134,7 +147,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +158,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -222,7 +235,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateRow['headers']['status-code']); foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } diff --git a/tests/e2e/Services/Tokens/TokensBase.php b/tests/e2e/Services/Tokens/TokensBase.php index a4461c06c2..ca6feed5fa 100644 --- a/tests/e2e/Services/Tokens/TokensBase.php +++ b/tests/e2e/Services/Tokens/TokensBase.php @@ -94,7 +94,7 @@ trait TokensBase $this->assertEquals(401, $failedPreview['body']['code']); $this->assertEquals(401, $failedPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedPreview['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedPreview['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedPreview['body']['message']); // Extended file preview. Should fail as an anonymous user with no form of any access to the file. $failedCustomPreview = $this->client->call( @@ -113,7 +113,7 @@ trait TokensBase $this->assertEquals(401, $failedCustomPreview['body']['code']); $this->assertEquals(401, $failedCustomPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedCustomPreview['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedCustomPreview['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedCustomPreview['body']['message']); // File view. Should fail as an anonymous user with no form of any access to the file. $failedView = $this->client->call( @@ -124,7 +124,7 @@ trait TokensBase $this->assertEquals(401, $failedView['body']['code']); $this->assertEquals(401, $failedView['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedView['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedView['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedView['body']['message']); // File download. Should fail as an anonymous user with no form of any access to the file. $failedDownload = $this->client->call( @@ -135,7 +135,7 @@ trait TokensBase $this->assertEquals(401, $failedDownload['body']['code']); $this->assertEquals(401, $failedDownload['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedDownload['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedDownload['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedDownload['body']['message']); return $data; } diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 42e433568f..7df5b8d1e6 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -7,6 +7,7 @@ use Appwrite\Utopia\Database\Documents\User; use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -33,6 +34,19 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; + + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + public function setUp(): void { /** @@ -65,7 +79,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -89,7 +103,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); diff --git a/tests/unit/Utopia/Database/Documents/UserTest.php b/tests/unit/Utopia/Database/Documents/UserTest.php index 4675e8d73f..d5706e7bec 100644 --- a/tests/unit/Utopia/Database/Documents/UserTest.php +++ b/tests/unit/Utopia/Database/Documents/UserTest.php @@ -14,13 +14,25 @@ use Utopia\Database\Validator\Roles; class UserTest extends TestCase { + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + /** * Reset Roles */ public function tearDown(): void { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); + $this->getAuthorization()->cleanRoles(); + $this->getAuthorization()->addRole(Role::any()->toString()); } public function testSessionVerify(): void @@ -197,7 +209,7 @@ class UserTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -233,7 +245,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -254,21 +266,21 @@ class UserTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles); // Enable single verification type $user['emailVerification'] = true; - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); } public function testPrivilegedUserRoles(): void { - Authorization::setRole(User::ROLE_OWNER); + $this->getAuthorization()->addRole(User::ROLE_OWNER); $user = new User([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -293,8 +305,7 @@ class UserTest extends TestCase ] ] ]); - - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -312,7 +323,7 @@ class UserTest extends TestCase public function testAppUserRoles(): void { - Authorization::setRole(User::ROLE_APPS); + $this->getAuthorization()->addRole(User::ROLE_APPS); $user = new User([ '$id' => ID::custom('123'), 'memberships' => [ @@ -336,7 +347,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); From 22f8a3eab9664dbcf2d536e1270e840751bebe2f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 7 Jan 2026 23:24:49 +1300 Subject: [PATCH 02/52] Sync merge --- app/controllers/general.php | 113 +++++++++--------- .../Storage/Http/Buckets/Files/Create.php | 18 +-- .../Storage/Http/Buckets/Files/Delete.php | 12 +- .../Http/Buckets/Files/Download/Get.php | 12 +- .../Storage/Http/Buckets/Files/Get.php | 10 +- .../Http/Buckets/Files/Preview/Get.php | 16 +-- .../Storage/Http/Buckets/Files/Push/Get.php | 12 +- .../Storage/Http/Buckets/Files/Update.php | 18 +-- .../Storage/Http/Buckets/Files/View/Get.php | 12 +- .../Storage/Http/Buckets/Files/XList.php | 16 +-- .../Modules/Storage/Http/Usage/Get.php | 5 +- .../Modules/Storage/Http/Usage/XList.php | 5 +- .../Platform/Workers/Certificates.php | 33 +++-- 13 files changed, 160 insertions(+), 122 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index ce229ee85f..f64ce21765 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1034,7 +1034,8 @@ App::init() ->inject('dbForPlatform') ->inject('queueForCertificates') ->inject('platform') - ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform) { + ->inject('authorization') + ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) { $hostname = $request->getHostname(); $cache = Config::getParam('hostnames', []); $platformHostnames = $platform['hostnames'] ?? []; @@ -1062,64 +1063,64 @@ App::init() } // 4. Check/create rule (requires DB access) - Authorization::disable(); - try { - // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $document = $isMd5 - ? $dbForPlatform->getDocument('rules', md5($domain->get())) - : $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$domain->get()]), + $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) { + try { + // TODO: (@Meldiron) Remove after 1.7.x migration + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $document = $isMd5 + ? $dbForPlatform->getDocument('rules', md5($domain->get())) + : $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]), + ]); + + if (!$document->isEmpty()) { + return; + } + + // 5. Create new rule + $owner = ''; + $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); + $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { + $funcDomain = $fallback; + } + + if ( + (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || + (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) + ) { + $owner = 'Appwrite'; + } + + $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); + $document = new Document([ + '$id' => $ruleId, + 'domain' => $domain->get(), + 'type' => 'api', + 'status' => 'verifying', + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getSequence(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') ]); - if (!$document->isEmpty()) { - return; + $dbForPlatform->createDocument('rules', $document); + + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + $queueForCertificates + ->setDomain($document) + ->setSkipRenewCheck(true) + ->trigger(); + } catch (Duplicate $e) { + Console::info('Certificate already exists'); + } finally { + $cache[$domain->get()] = true; + Config::setParam('hostnames', $cache); } - - // 5. Create new rule - $owner = ''; - $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); - $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - - if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { - $funcDomain = $fallback; - } - - if ( - (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || - (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) - ) { - $owner = 'Appwrite'; - } - - $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); - $document = new Document([ - '$id' => $ruleId, - 'domain' => $domain->get(), - 'type' => 'api', - 'status' => 'verifying', - 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), - 'search' => implode(' ', [$ruleId, $domain->get()]), - 'owner' => $owner, - 'region' => $console->getAttribute('region') - ]); - - $dbForPlatform->createDocument('rules', $document); - - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); - $queueForCertificates - ->setDomain($document) - ->setSkipRenewCheck(true) - ->trigger(); - } catch (Duplicate $e) { - Console::info('Certificate already exists'); - } finally { - $cache[$domain->get()] = true; - Config::setParam('hostnames', $cache); - Authorization::reset(); - } + }); }); App::options() diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index b2d9af5a08..201976757b 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -90,6 +90,7 @@ class Create extends Action ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') + ->inject('authorization') ->callback($this->action(...)); } @@ -105,12 +106,13 @@ class Create extends Action Event $queueForEvents, string $mode, Device $deviceForFiles, - Device $deviceForLocal + Device $deviceForLocal, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -141,7 +143,7 @@ class Create extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser) { foreach (\Utopia\Database\Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -154,7 +156,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -383,7 +385,7 @@ class Create extends Action if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } else { if ($file->isEmpty()) { @@ -430,7 +432,7 @@ class Create extends Action } try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index eccacaafd2..243757e1c5 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -64,6 +64,7 @@ class Delete extends Action ->inject('queueForEvents') ->inject('deviceForFiles') ->inject('queueForDeletes') + ->inject('authorization') ->callback($this->action(...)); } @@ -75,11 +76,12 @@ class Delete extends Action Event $queueForEvents, Device $deviceForFiles, DeleteEvent $queueForDeletes, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -93,7 +95,7 @@ class Delete extends Action } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -125,7 +127,7 @@ class Delete extends Action if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = $authorization->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index 45e3b83375..48ba9a0805 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -68,6 +68,7 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -80,13 +81,14 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization, ) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -104,7 +106,7 @@ class Get extends Action $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index 77f163e5fb..45efac241d 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -49,6 +49,7 @@ class Get extends Action ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -57,11 +58,12 @@ class Get extends Action string $fileId, Response $response, Database $dbForProject, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -77,7 +79,7 @@ class Get extends Action if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 9c4e49d0bb..063d581738 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -90,6 +90,7 @@ class Get extends Action ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -114,7 +115,8 @@ class Get extends Action Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, - Document $project + Document $project, + Authorization $authorization ) { if (!\extension_loaded('imagick')) { @@ -122,10 +124,10 @@ class Get extends Action } /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -147,7 +149,7 @@ class Get extends Action $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -269,11 +271,11 @@ class Get extends Action $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php index 67372435b1..516343e23f 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('project') ->inject('mode') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -64,7 +65,8 @@ class Get extends Action Database $dbForPlatform, Document $project, string $mode, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization ) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -86,15 +88,15 @@ class Get extends Action $disposition = $decoded['disposition'] ?? 'inline'; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index be78cc358b..1a7980d3a8 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -62,6 +62,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,12 +73,13 @@ class Update extends Action ?array $permissions, Response $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -91,7 +93,7 @@ class Update extends Action } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -105,7 +107,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -118,7 +120,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -139,7 +141,7 @@ class Update extends Action if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index 41ee95b165..ed525efab1 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -69,6 +69,7 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -81,13 +82,14 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization ) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -105,7 +107,7 @@ class Get extends Action $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index e46fdb2a0a..eebf96f960 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -61,6 +61,7 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('mode') + ->inject('authorization') ->callback($this->action(...)); } @@ -71,12 +72,13 @@ class XList extends Action bool $includeTotal, Response $response, Database $dbForProject, - string $mode + string $mode, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -119,7 +121,7 @@ class XList extends Action if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -136,8 +138,8 @@ class XList extends Action $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $includeTotal ? Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; + $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $includeTotal ? $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php index b816e83f72..a7bda355da 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php @@ -54,10 +54,11 @@ class Get extends Action ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) + public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, Authorization $authorization) { $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -75,7 +76,7 @@ class Get extends Action str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php index d29fa7c1b4..44fdd54e8c 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php @@ -49,10 +49,11 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -63,7 +64,7 @@ class XList extends Action METRIC_FILES_STORAGE, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 5132687279..33ebd39092 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -21,6 +21,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -58,6 +59,7 @@ class Certificates extends Action ->inject('log') ->inject('certificates') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,6 +74,8 @@ class Certificates extends Action * @param Certificate $queueForCertificates * @param Log $log * @param CertificatesAdapter $certificates + * @param array $plan + * @param ValidatorAuthorization $authorization * @return void * @throws Throwable * @throws \Utopia\Database\Exception @@ -87,7 +91,8 @@ class Certificates extends Action Certificate $queueForCertificates, Log $log, CertificatesAdapter $certificates, - array $plan + array $plan, + ValidatorAuthorization $authorization, ): void { $payload = $message->getPayload() ?? []; @@ -106,11 +111,11 @@ class Certificates extends Action switch ($action) { case Certificate::ACTION_DOMAIN_VERIFICATION: - $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $validationDomain); + $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $authorization, $validationDomain); break; case Certificate::ACTION_GENERATION: - $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $validationDomain); + $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); break; default: @@ -127,10 +132,12 @@ class Certificates extends Action * @param Realtime $queueForRealtime * @param Certificate $queueForCertificates * @param Log $log + * @param ValidatorAuthorization $authorization * @param string|null $validationDomain * @return void - * @throws Throwable * @throws \Utopia\Database\Exception + * @throws NotFound + * @throws \Utopia\Database\Exception\Query */ private function handleDomainVerificationAction( Domain $domain, @@ -141,12 +148,13 @@ class Certificates extends Action Realtime $queueForRealtime, Certificate $queueForCertificates, Log $log, + ValidatorAuthorization $authorization, ?string $validationDomain = null ): void { // Get rule $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ + ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); @@ -195,15 +203,23 @@ class Certificates extends Action * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents + * @param Webhook $queueForWebhooks * @param Func $queueForFunctions * @param Realtime $queueForRealtime + * @param Log $log * @param CertificatesAdapter $certificates + * @param ValidatorAuthorization $authorization * @param bool $skipRenewCheck * @param array $plan * @param string|null $validationDomain * @return void + * @throws Authorization + * @throws Conflict + * @throws NotFound + * @throws Structure * @throws Throwable * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Query */ private function handleCertificateGenerationAction( Domain $domain, @@ -216,6 +232,7 @@ class Certificates extends Action Realtime $queueForRealtime, Log $log, CertificatesAdapter $certificates, + ValidatorAuthorization $authorization, bool $skipRenewCheck = false, array $plan = [], ?string $validationDomain = null @@ -252,8 +269,8 @@ class Certificates extends Action // Get rule document for domain // TODO: (@Meldiron) Remove after 1.7.x migration $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ + ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); From b567cd53413cf92cec45ae2f9d5c9d0f4d0ff6cf Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 8 Jan 2026 15:01:30 +1300 Subject: [PATCH 03/52] Update storage module for auth instance --- .../Storage/Http/Buckets/Files/Create.php | 20 +++++++++---------- .../Storage/Http/Buckets/Files/Delete.php | 10 +++++----- .../Http/Buckets/Files/Download/Get.php | 6 +++--- .../Storage/Http/Buckets/Files/Get.php | 6 +++--- .../Http/Buckets/Files/Preview/Get.php | 6 +++--- .../Storage/Http/Buckets/Files/Update.php | 8 ++++---- .../Storage/Http/Buckets/Files/View/Get.php | 6 +++--- .../Storage/Http/Buckets/Files/XList.php | 6 +++--- 8 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index 201976757b..acd0ab02c5 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -22,6 +22,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -118,15 +119,14 @@ class Create extends Action throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $allowedPermissions = [ - \Utopia\Database\Database::PERMISSION_READ, - \Utopia\Database\Database::PERMISSION_UPDATE, - \Utopia\Database\Database::PERMISSION_DELETE, + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, ]; // Map aggregate permissions to into the set of individual permissions they represent. @@ -156,7 +156,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -381,8 +381,7 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); @@ -426,8 +425,7 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index 243757e1c5..ca376842e2 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -88,10 +89,9 @@ class Delete extends Action } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_DELETE); - $valid = $validator->isValid($bucket->getDelete()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for delete @@ -102,8 +102,8 @@ class Delete extends Action } // Make sure we don't delete the file before the document permission check occurs - if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if ($fileSecurity && !$valid && !$authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $deviceDeleted = false; diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index 48ba9a0805..bbceff51ec 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -96,10 +97,9 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index 45efac241d..caaab29efc 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -10,6 +10,7 @@ use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -70,10 +71,9 @@ class Get extends Action } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 063d581738..7ab3e713bc 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -17,6 +17,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Image\Image; use Utopia\Platform\Action; @@ -139,10 +140,9 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index 1a7980d3a8..57856c1564 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -14,6 +14,7 @@ use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -86,10 +87,9 @@ class Update extends Action } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $valid = $validator->isValid($bucket->getUpdate()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for update @@ -120,7 +120,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index ed525efab1..3874fedacf 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -15,6 +15,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -97,10 +98,9 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index eebf96f960..3663b56fab 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -16,6 +16,7 @@ use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -85,10 +86,9 @@ class XList extends Action } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } try { From c1ab9da74090b30c31db32ae602af69991e484e9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 8 Jan 2026 17:48:20 +1300 Subject: [PATCH 04/52] Update migrations --- composer.json | 8 +-- composer.lock | 52 +++++++------------- src/Appwrite/Platform/Workers/Migrations.php | 15 +++--- 3 files changed, 25 insertions(+), 50 deletions(-) diff --git a/composer.json b/composer.json index 565d22d80b..af63ccd4bd 100644 --- a/composer.json +++ b/composer.json @@ -64,7 +64,7 @@ "utopia-php/locale": "0.8.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.20.*", - "utopia-php/migration": "1.3.*", + "utopia-php/migration": "1.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", @@ -100,12 +100,6 @@ "provide": { "ext-phpiredis": "*" }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/utopia-php/migration.git" - } - ], "config": { "platform": { "php": "8.3" diff --git a/composer.lock b/composer.lock index a53b751f1d..deeea27ec5 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": "a3bbbe3de978c5cb73dc91c872cbc1c4", + "content-hash": "2c199847e810b281ec2368c4c93481ea", "packages": [ { "name": "adhocore/jwt", @@ -69,16 +69,16 @@ }, { "name": "appwrite/appwrite", - "version": "15.1.0", + "version": "19.1.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-for-php.git", - "reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b" + "reference": "8738e812062f899c85b2598eef43d6a247f08a56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/c438b3885071ac7c0329199dce5e6f6a24dd215b", - "reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b", + "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/8738e812062f899c85b2598eef43d6a247f08a56", + "reference": "8738e812062f899c85b2598eef43d6a247f08a56", "shasum": "" }, "require": { @@ -87,7 +87,7 @@ "php": ">=7.1.0" }, "require-dev": { - "mockery/mockery": "^1.6.6", + "mockery/mockery": "^1.6.12", "phpunit/phpunit": "^10" }, "type": "library", @@ -104,10 +104,10 @@ "support": { "email": "team@appwrite.io", "issues": "https://github.com/appwrite/sdk-for-php/issues", - "source": "https://github.com/appwrite/sdk-for-php/tree/15.1.0", + "source": "https://github.com/appwrite/sdk-for-php/tree/19.1.0", "url": "https://appwrite.io/support" }, - "time": "2025-08-01T04:50:51+00:00" + "time": "2025-12-18T08:07:43+00:00" }, { "name": "appwrite/php-clamav", @@ -4515,20 +4515,20 @@ }, { "name": "utopia-php/migration", - "version": "1.3.5", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "6f366f1d4ac2796e59a97d1ba28cedc355e7122e" + "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/6f366f1d4ac2796e59a97d1ba28cedc355e7122e", - "reference": "6f366f1d4ac2796e59a97d1ba28cedc355e7122e", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/4cb7a0e65a36058d153ef5643090414c6525e4a2", + "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2", "shasum": "" }, "require": { - "appwrite/appwrite": "15.*", + "appwrite/appwrite": "19.*", "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", @@ -4550,25 +4550,7 @@ "Utopia\\Migration\\": "src/Migration" } }, - "autoload-dev": { - "psr-4": { - "Utopia\\Tests\\": "tests/Migration" - } - }, - "scripts": { - "test": [ - "./vendor/bin/phpunit" - ], - "lint": [ - "./vendor/bin/pint --test" - ], - "format": [ - "./vendor/bin/pint" - ], - "check": [ - "./vendor/bin/phpstan analyse --level 3 src tests --memory-limit 2G" - ] - }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4581,10 +4563,10 @@ "utopia" ], "support": { - "source": "https://github.com/utopia-php/migration/tree/1.3.5", - "issues": "https://github.com/utopia-php/migration/issues" + "issues": "https://github.com/utopia-php/migration/issues", + "source": "https://github.com/utopia-php/migration/tree/1.4.2" }, - "time": "2025-11-25T11:18:29+00:00" + "time": "2026-01-08T04:46:18+00:00" }, { "name": "utopia-php/mongo", diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 17f9c6c1b0..6ef2f1899c 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -444,14 +444,14 @@ class Migrations extends Action $destination?->success(); $source?->success(); - // todo: Move to CSV hook + // TODO: Move to CSV hook if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization); } } } finally { - $source?->cleanUp(); - $destination?->cleanUp(); + $source?->cleanup(); + $destination?->cleanup(); $transfer = null; $source = null; @@ -466,11 +466,10 @@ class Migrations extends Action * @param Document $project * @param Document $migration * @param Mail $queueForMails + * @param Realtime $queueForRealtime + * @param array $platform + * @param Authorization $authorization * @return void - * @throws AuthorizationException - * @throws Structure - * @throws \Utopia\Database\Exception - * @throws Exception */ protected function handleCSVExportComplete( Document $project, From e3d6fc123fb68f5ce3ddbd6929c1cafa10c55d7a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 8 Jan 2026 18:11:37 +1300 Subject: [PATCH 05/52] Update lock --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index c87f2c068f..0bc3caff18 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": "2c199847e810b281ec2368c4c93481ea", + "content-hash": "ad3d3cc3b265daf8657cb43836fc9879", "packages": [ { "name": "adhocore/jwt", @@ -3898,16 +3898,16 @@ }, { "name": "utopia-php/database", - "version": "4.3.0", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee" + "reference": "783193d5cdc723b3784e8fb399068b17d4228d53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/fe7a1326ad623609e65587fe8c01a630a7075fee", - "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee", + "url": "https://api.github.com/repos/utopia-php/database/zipball/783193d5cdc723b3784e8fb399068b17d4228d53", + "reference": "783193d5cdc723b3784e8fb399068b17d4228d53", "shasum": "" }, "require": { @@ -3950,9 +3950,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.3.0" + "source": "https://github.com/utopia-php/database/tree/4.4.0" }, - "time": "2025-11-14T03:43:10+00:00" + "time": "2026-01-08T04:54:39+00:00" }, { "name": "utopia-php/detector", From 4c1417944d3a6e1a470265f484ce3f834d7bd5e6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 8 Jan 2026 18:54:52 +1300 Subject: [PATCH 06/52] Fix bucket stats auth --- .../Modules/Storage/Http/Buckets/Get.php | 23 ++++++------ .../Modules/Storage/Http/Buckets/XList.php | 35 +++++++++++-------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php index 5c3515122b..4e75de27c8 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } @@ -59,7 +60,8 @@ class Get extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB + callable $getLogsDB, + Authorization $authorization, ): void { $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -75,19 +77,20 @@ class Get extends Action $statsDocId = md5('_inf_' . $metric); - $dbForLogs = call_user_func($getLogsDB, $project); - $storageStats = Authorization::skip( - fn () => $dbForLogs->getDocument( + $totalSize = 0; + + try { + $dbForLogs = $getLogsDB($project); + $storageStats = $authorization->skip(fn () => $dbForLogs->getDocument( 'stats', $statsDocId, [Query::select(['value'])] - ) - ); + )); - /** - * The value can be 0 if stats were not aggregated when this request was made! - */ - $totalSize = $storageStats->isEmpty() ? 0 : $storageStats->getAttribute('value', 0); + $totalSize = $storageStats->getAttribute('value', 0); + } catch (\Throwable) { + // Stats may not be available, default to 0 + } $bucket->setAttribute('totalSize', $totalSize); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php index a2c880ce08..601d9b5321 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php @@ -58,6 +58,7 @@ class XList extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,7 +69,8 @@ class XList extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB + callable $getLogsDB, + Authorization $authorization ) { try { $queries = Query::parseQueries($queries); @@ -117,7 +119,6 @@ class XList extends Action if (!empty($buckets)) { $bucketByStatsId = []; - $dbForLogs = call_user_func($getLogsDB, $project); foreach ($buckets as $bucket) { $metric = str_replace( @@ -134,22 +135,28 @@ class XList extends Action $bucket->setAttribute('totalSize', 0); } - /* @type Document[] $stats */ - $stats = Authorization::skip(function () use ($dbForLogs, $bucketByStatsId) { - $statsIds = array_keys($bucketByStatsId); + try { + $dbForLogs = $getLogsDB($project); - return $dbForLogs->find('stats', [ - Query::equal('$id', $statsIds), - Query::select(['value']), - ]); - }); + /* @var array $stats */ + $stats = $authorization->skip(function () use ($dbForLogs, $bucketByStatsId) { + $statsIds = array_keys($bucketByStatsId); - foreach ($stats as $stat) { - $bucket = $bucketByStatsId[$stat->getId()]; + return $dbForLogs->find('stats', [ + Query::equal('$id', $statsIds), + Query::select(['value']), + ]); + }); - if ($bucket) { - $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); + foreach ($stats as $stat) { + $bucket = $bucketByStatsId[$stat->getId()]; + + if ($bucket) { + $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); + } } + } catch (\Throwable) { + // Stats may not be available, default to 0 } } From 2131a0cea127eae03f357ea735457b3968ceafcc Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 13 Jan 2026 16:21:43 +1300 Subject: [PATCH 07/52] Sync auth --- src/Appwrite/Platform/Modules/Avatars/Http/Action.php | 10 +++++----- .../Modules/Avatars/Http/Cards/Cloud/Back/Get.php | 5 +++-- .../Modules/Avatars/Http/Cards/Cloud/Front/Get.php | 5 +++-- .../Modules/Avatars/Http/Cards/Cloud/OG/Get.php | 5 +++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index 1ff2f8f706..f6ca2911a9 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -21,7 +21,7 @@ class Action extends PlatformAction return \dirname(__DIR__, 6); } - protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response): void + protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response, Authorization $authorization): void { $code = \strtolower($code); $type = \strtolower($type); @@ -58,10 +58,10 @@ class Action extends PlatformAction unset($image); } - protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger): array + protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array { try { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -112,7 +112,7 @@ class Action extends PlatformAction ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); + $authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -120,7 +120,7 @@ class Action extends PlatformAction do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index 1c0de4001e..afe2c8088c 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index 9d53991dd6..ab5c6b1bf4 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index f7c983db78..d18acf487e 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); From 2d6348bf5d980d79ff0af51d0608a1c0d2185e1f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 13 Jan 2026 17:22:05 +1300 Subject: [PATCH 08/52] Fix health --- app/controllers/api/health.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 8f4a9e881d..cda2d94911 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -23,10 +23,14 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Pool as CachePool; +use Utopia\Cache\Cache; use Utopia\Config\Config; use Utopia\Database\Adapter\Pool as DatabasePool; +use Utopia\Database\Database as UtopiaDatabase; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -101,7 +105,8 @@ App::get('/v1/health/db') )) ->inject('response') ->inject('pools') - ->action(function (Response $response, Group $pools) { + ->inject('authorization') + ->action(action: function (Response $response, Group $pools, Authorization $authorization) { $output = []; $failures = []; @@ -114,10 +119,14 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); + $cache = new Cache(new None()); + $db = (new UtopiaDatabase($adapter, $cache)) + ->setDatabase($database) + ->setAuthorization($authorization); $checkStart = \microtime(true); - if ($adapter->ping()) { + if ($db->ping()) { $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', From 3d27b760519a10308404f423b917c6095c350149 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 13 Jan 2026 18:05:46 +1300 Subject: [PATCH 09/52] Fix avatars --- src/Appwrite/Platform/Modules/Avatars/Http/Action.php | 2 +- src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php | 2 +- .../Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php | 2 +- .../Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php | 2 +- .../Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php | 2 +- src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php | 2 +- src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index f6ca2911a9..bf7d01764f 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -21,7 +21,7 @@ class Action extends PlatformAction return \dirname(__DIR__, 6); } - protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response, Authorization $authorization): void + protected function avatar(string $type, string $code, int $width, int $height, int $quality, Response $response): void { $code = \strtolower($code); $type = \strtolower($type); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php index 04648752b5..637ea647ef 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('browsers', $code, $width, $height, $quality, $response); + $this->avatar('browsers', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index afe2c8088c..a6a013ef21 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -69,7 +69,7 @@ class Get extends Action $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index ab5c6b1bf4..f8e7a35b05 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -70,7 +70,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index d18acf487e..37776a3466 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -74,7 +74,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php index 5d3429b377..87357f14c7 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('credit-cards', $code, $width, $height, $quality, $response); + $this->avatar('credit-cards', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php index c3960c134e..8230b15f50 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('flags', $code, $width, $height, $quality, $response); + $this->avatar('flags', $code, $width, $height, $quality, $response); } } From 8e688bad4db2974b88ee37a985714017d0e1fa9c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 13 Jan 2026 18:36:38 +1300 Subject: [PATCH 10/52] Revert ping --- app/controllers/api/health.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index cda2d94911..bee551d2ed 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -119,14 +119,9 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); - $cache = new Cache(new None()); - $db = (new UtopiaDatabase($adapter, $cache)) - ->setDatabase($database) - ->setAuthorization($authorization); - $checkStart = \microtime(true); - if ($db->ping()) { + if ($adapter->ping()) { $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', From 515a34c180737f2ce2c73bf419a326ef6e191a4b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 13 Jan 2026 18:52:16 +1300 Subject: [PATCH 11/52] Set health adapter auth --- app/controllers/api/health.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index bee551d2ed..c57e001be8 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -119,6 +119,7 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); + $adapter->setAuthorization($authorization); $checkStart = \microtime(true); if ($adapter->ping()) { From 03812cf7bf63d09baa983289656449ed93dda4c9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 13 Jan 2026 18:59:55 +1300 Subject: [PATCH 12/52] Lint --- app/controllers/api/health.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index c57e001be8..d6388185d3 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -23,12 +23,9 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Pool as CachePool; -use Utopia\Cache\Cache; use Utopia\Config\Config; use Utopia\Database\Adapter\Pool as DatabasePool; -use Utopia\Database\Database as UtopiaDatabase; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Domains\Validator\PublicDomain; From 5ef675bcdd96aeb828dad2080e2102075a5069a3 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 13 Jan 2026 13:38:32 +0530 Subject: [PATCH 13/52] release cli sdk 13.0.0 rc5 --- app/config/sdks.php | 2 +- docs/sdks/cli/CHANGELOG.md | 17 +++++++++++++++++ src/Appwrite/Platform/Tasks/SDKs.php | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/config/sdks.php b/app/config/sdks.php index 9b5d17176f..b9d091f24d 100644 --- a/app/config/sdks.php +++ b/app/config/sdks.php @@ -227,7 +227,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '12.0.1', + 'version' => '13.0.0-rc.5', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/docs/sdks/cli/CHANGELOG.md b/docs/sdks/cli/CHANGELOG.md index 9f1f02bbd0..81dac8a668 100644 --- a/docs/sdks/cli/CHANGELOG.md +++ b/docs/sdks/cli/CHANGELOG.md @@ -1,5 +1,22 @@ # Change Log +## 13.0.0-rc.4 + +- Fix CLI ES module import issues + +## 13.0.0-rc.3 + +- Add `Schema` class for programmatically pushing and pulling appwrite config +- Add client side db generation using `schema.db.generate()` command + +## 13.0.0-rc.2 + +- Fixes a lot of typescript errors throughout the codebase + +## 13.0.0-rc.1 + +- Migrates codebase from JavaScript to TypeScript + ## 12.0.1 Fix type generation for `point`, `lineString` and `polygon` columns diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index c3a67d7fbb..8a3eef2d34 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -399,7 +399,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ->setDefaultHeaders([ 'X-Appwrite-Response-Format' => '1.8.0', ]) - ->setExclude($language['exclude'] ?? []); + ->setExclude($language['exclude'] ?? []) + ->setTest(false); // Make sure we have a clean slate. // Otherwise, all files in this dir will be pushed, From 81e64afe7a79b3b11509f4c66098940dcc305d10 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 13 Jan 2026 13:38:44 +0530 Subject: [PATCH 14/52] changelog --- docs/sdks/cli/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/sdks/cli/CHANGELOG.md b/docs/sdks/cli/CHANGELOG.md index 81dac8a668..b55c6e5934 100644 --- a/docs/sdks/cli/CHANGELOG.md +++ b/docs/sdks/cli/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 13.0.0-rc.5 + +- Fix push all command not working correctly + ## 13.0.0-rc.4 - Fix CLI ES module import issues From c79019f96036c90d662ae514e910064670a858d8 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 13 Jan 2026 13:58:57 +0530 Subject: [PATCH 15/52] regen: specs. --- app/config/sdks.php | 2 +- app/config/specs/open-api3-latest-client.json | 86 ++-- .../specs/open-api3-latest-console.json | 465 +++++++++--------- app/config/specs/open-api3-latest-server.json | 307 ++++++------ app/config/specs/swagger2-latest-client.json | 86 ++-- app/config/specs/swagger2-latest-console.json | 465 +++++++++--------- app/config/specs/swagger2-latest-server.json | 307 ++++++------ docs/sdks/flutter/CHANGELOG.md | 4 + 8 files changed, 865 insertions(+), 857 deletions(-) diff --git a/app/config/sdks.php b/app/config/sdks.php index 9b5d17176f..eee8f03b70 100644 --- a/app/config/sdks.php +++ b/app/config/sdks.php @@ -60,7 +60,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '20.3.2', + 'version' => '20.3.3', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index fd35c3b73c..e03aaee4ef 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -551,7 +551,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -623,7 +623,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -747,7 +747,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -887,7 +887,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1011,7 +1011,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1145,7 +1145,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1283,7 +1283,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1384,7 +1384,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1483,7 +1483,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1582,7 +1582,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -4039,7 +4039,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4167,7 +4167,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4301,7 +4301,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4361,7 +4361,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4851,7 +4851,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4935,7 +4935,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5029,7 +5029,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5123,7 +5123,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -7598,7 +7598,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -7652,7 +7652,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -7706,7 +7706,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -7760,7 +7760,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -7814,7 +7814,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -7868,7 +7868,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -7922,7 +7922,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -7976,7 +7976,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -8030,7 +8030,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -8084,7 +8084,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -8138,7 +8138,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -8222,7 +8222,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -10574,7 +10574,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -10663,7 +10663,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -10750,7 +10750,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -10814,7 +10814,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -10890,7 +10890,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -10956,7 +10956,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -11055,7 +11055,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -11175,7 +11175,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -11249,7 +11249,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -11345,7 +11345,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -11421,7 +11421,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -11521,7 +11521,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -11584,7 +11584,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 952f83af6d..617580e3e2 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -584,7 +584,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -655,7 +655,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -778,7 +778,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -917,7 +917,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1040,7 +1040,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1173,7 +1173,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1310,7 +1310,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1410,7 +1410,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1508,7 +1508,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1606,7 +1606,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -4032,7 +4032,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4160,7 +4160,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4294,7 +4294,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4354,7 +4354,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4844,7 +4844,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4928,7 +4928,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5022,7 +5022,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5116,7 +5116,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -16229,7 +16229,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -16283,7 +16283,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -16337,7 +16337,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -16388,7 +16388,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -16439,7 +16439,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -16490,7 +16490,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -16552,7 +16552,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -16603,7 +16603,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -16654,7 +16654,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -16718,7 +16718,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -16782,7 +16782,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -16857,7 +16857,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -16921,7 +16921,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -16965,6 +16965,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -17011,7 +17012,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -17075,7 +17076,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -17139,7 +17140,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -17203,7 +17204,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -17267,7 +17268,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -17331,7 +17332,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -17395,7 +17396,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -17459,7 +17460,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -17523,7 +17524,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -17574,7 +17575,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -17625,7 +17626,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -17676,7 +17677,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -17730,7 +17731,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -17784,7 +17785,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -17838,7 +17839,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -17892,7 +17893,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -17946,7 +17947,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -18000,7 +18001,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -18054,7 +18055,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -18108,7 +18109,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -18196,7 +18197,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -18342,7 +18343,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -18500,7 +18501,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -18677,7 +18678,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -18874,7 +18875,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -19055,7 +19056,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -19242,7 +19243,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -19296,7 +19297,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -19359,7 +19360,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -19446,7 +19447,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -19533,7 +19534,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -19621,7 +19622,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -19800,7 +19801,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -19981,7 +19982,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -20133,7 +20134,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -20286,7 +20287,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -20404,7 +20405,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -20525,7 +20526,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -20622,7 +20623,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -20722,7 +20723,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -20829,7 +20830,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -20939,7 +20940,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -21046,7 +21047,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -21156,7 +21157,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -21387,7 +21388,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -21618,7 +21619,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -21715,7 +21716,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -21815,7 +21816,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -21912,7 +21913,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -22012,7 +22013,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -22109,7 +22110,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -22209,7 +22210,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -22306,7 +22307,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -22406,7 +22407,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -22460,7 +22461,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -22523,7 +22524,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -22610,7 +22611,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -22697,7 +22698,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -22783,7 +22784,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -22867,7 +22868,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -22928,7 +22929,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -23008,7 +23009,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -23071,7 +23072,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -23158,7 +23159,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -23254,7 +23255,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -23345,7 +23346,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -23409,7 +23410,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -23485,7 +23486,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 232, + "weight": 221, "cookies": false, "type": "", "demo": "migrations\/list.md", @@ -23571,7 +23572,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 226, + "weight": 215, "cookies": false, "type": "", "demo": "migrations\/create-appwrite-migration.md", @@ -23680,7 +23681,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 234, + "weight": 223, "cookies": false, "type": "", "demo": "migrations\/get-appwrite-report.md", @@ -23794,7 +23795,7 @@ "x-appwrite": { "method": "createCSVExport", "group": null, - "weight": 231, + "weight": 220, "cookies": false, "type": "", "demo": "migrations\/create-csv-export.md", @@ -23909,7 +23910,7 @@ "x-appwrite": { "method": "createCSVImport", "group": null, - "weight": 230, + "weight": 219, "cookies": false, "type": "", "demo": "migrations\/create-csv-import.md", @@ -23994,7 +23995,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 227, + "weight": 216, "cookies": false, "type": "", "demo": "migrations\/create-firebase-migration.md", @@ -24085,7 +24086,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 235, + "weight": 224, "cookies": false, "type": "", "demo": "migrations\/get-firebase-report.md", @@ -24172,7 +24173,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 229, + "weight": 218, "cookies": false, "type": "", "demo": "migrations\/create-n-host-migration.md", @@ -24299,7 +24300,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 237, + "weight": 226, "cookies": false, "type": "", "demo": "migrations\/get-n-host-report.md", @@ -24448,7 +24449,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 228, + "weight": 217, "cookies": false, "type": "", "demo": "migrations\/create-supabase-migration.md", @@ -24569,7 +24570,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 236, + "weight": 225, "cookies": false, "type": "", "demo": "migrations\/get-supabase-report.md", @@ -24709,7 +24710,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 233, + "weight": 222, "cookies": false, "type": "", "demo": "migrations\/get.md", @@ -24768,7 +24769,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 238, + "weight": 227, "cookies": false, "type": "", "demo": "migrations\/retry.md", @@ -24820,7 +24821,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 239, + "weight": 228, "cookies": false, "type": "", "demo": "migrations\/delete.md", @@ -24881,7 +24882,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 138, + "weight": 127, "cookies": false, "type": "", "demo": "project\/get-usage.md", @@ -24970,7 +24971,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 140, + "weight": 129, "cookies": false, "type": "", "demo": "project\/list-variables.md", @@ -25017,7 +25018,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 139, + "weight": 128, "cookies": false, "type": "", "demo": "project\/create-variable.md", @@ -25096,7 +25097,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 141, + "weight": 130, "cookies": false, "type": "", "demo": "project\/get-variable.md", @@ -25155,7 +25156,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 142, + "weight": 131, "cookies": false, "type": "", "demo": "project\/update-variable.md", @@ -25238,7 +25239,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 143, + "weight": 132, "cookies": false, "type": "", "demo": "project\/delete-variable.md", @@ -25324,7 +25325,7 @@ "parameters": [ { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search", "required": false, "schema": { "type": "array", @@ -25382,7 +25383,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 92, + "weight": 81, "cookies": false, "type": "", "demo": "projects\/create.md", @@ -25517,7 +25518,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 93, + "weight": 82, "cookies": false, "type": "", "demo": "projects\/get.md", @@ -25576,7 +25577,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 94, + "weight": 83, "cookies": false, "type": "", "demo": "projects\/update.md", @@ -25692,7 +25693,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 111, + "weight": 100, "cookies": false, "type": "", "demo": "projects\/delete.md", @@ -25753,7 +25754,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 98, + "weight": 87, "cookies": false, "type": "", "demo": "projects\/update-api-status.md", @@ -25910,7 +25911,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 99, + "weight": 88, "cookies": false, "type": "", "demo": "projects\/update-api-status-all.md", @@ -26050,7 +26051,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 104, + "weight": 93, "cookies": false, "type": "", "demo": "projects\/update-auth-duration.md", @@ -26130,7 +26131,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 103, + "weight": 92, "cookies": false, "type": "", "demo": "projects\/update-auth-limit.md", @@ -26210,7 +26211,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 109, + "weight": 98, "cookies": false, "type": "", "demo": "projects\/update-auth-sessions-limit.md", @@ -26290,7 +26291,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 102, + "weight": 91, "cookies": false, "type": "", "demo": "projects\/update-memberships-privacy.md", @@ -26382,7 +26383,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 110, + "weight": 99, "cookies": false, "type": "", "demo": "projects\/update-mock-numbers.md", @@ -26465,7 +26466,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 107, + "weight": 96, "cookies": false, "type": "", "demo": "projects\/update-auth-password-dictionary.md", @@ -26545,7 +26546,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 106, + "weight": 95, "cookies": false, "type": "", "demo": "projects\/update-auth-password-history.md", @@ -26625,7 +26626,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 108, + "weight": 97, "cookies": false, "type": "", "demo": "projects\/update-personal-data-check.md", @@ -26705,7 +26706,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 101, + "weight": 90, "cookies": false, "type": "", "demo": "projects\/update-session-alerts.md", @@ -26785,7 +26786,7 @@ "x-appwrite": { "method": "updateSessionInvalidation", "group": "auth", - "weight": 137, + "weight": 126, "cookies": false, "type": "", "demo": "projects\/update-session-invalidation.md", @@ -26865,7 +26866,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 105, + "weight": 94, "cookies": false, "type": "", "demo": "projects\/update-auth-status.md", @@ -27346,7 +27347,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 123, + "weight": 112, "cookies": false, "type": "", "demo": "projects\/create-jwt.md", @@ -27493,7 +27494,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 119, + "weight": 108, "cookies": false, "type": "", "demo": "projects\/list-keys.md", @@ -27563,7 +27564,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 118, + "weight": 107, "cookies": false, "type": "", "demo": "projects\/create-key.md", @@ -27718,7 +27719,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 120, + "weight": 109, "cookies": false, "type": "", "demo": "projects\/get-key.md", @@ -27787,7 +27788,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 121, + "weight": 110, "cookies": false, "type": "", "demo": "projects\/update-key.md", @@ -27943,7 +27944,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 122, + "weight": 111, "cookies": false, "type": "", "demo": "projects\/delete-key.md", @@ -28096,7 +28097,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 100, + "weight": 89, "cookies": false, "type": "", "demo": "projects\/update-o-auth-2.md", @@ -28239,7 +28240,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 125, + "weight": 114, "cookies": false, "type": "", "demo": "projects\/list-platforms.md", @@ -28309,7 +28310,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 124, + "weight": 113, "cookies": false, "type": "", "demo": "projects\/create-platform.md", @@ -28429,7 +28430,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 126, + "weight": 115, "cookies": false, "type": "", "demo": "projects\/get-platform.md", @@ -28498,7 +28499,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 127, + "weight": 116, "cookies": false, "type": "", "demo": "projects\/update-platform.md", @@ -28594,7 +28595,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 128, + "weight": 117, "cookies": false, "type": "", "demo": "projects\/delete-platform.md", @@ -28665,7 +28666,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 96, + "weight": 85, "cookies": false, "type": "", "demo": "projects\/update-service-status.md", @@ -28768,7 +28769,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 97, + "weight": 86, "cookies": false, "type": "", "demo": "projects\/update-service-status-all.md", @@ -28848,7 +28849,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 129, + "weight": 118, "cookies": false, "type": "", "demo": "projects\/update-smtp.md", @@ -29043,7 +29044,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 130, + "weight": 119, "cookies": false, "type": "", "demo": "projects\/create-smtp-test.md", @@ -29255,7 +29256,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 95, + "weight": 84, "cookies": false, "type": "", "demo": "projects\/update-team.md", @@ -29335,7 +29336,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 132, + "weight": 121, "cookies": false, "type": "", "demo": "projects\/get-email-template.md", @@ -29560,7 +29561,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 134, + "weight": 123, "cookies": false, "type": "", "demo": "projects\/update-email-template.md", @@ -29825,7 +29826,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 136, + "weight": 125, "cookies": false, "type": "", "demo": "projects\/delete-email-template.md", @@ -30052,7 +30053,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 131, + "weight": 120, "cookies": false, "type": "", "demo": "projects\/get-sms-template.md", @@ -30338,7 +30339,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 133, + "weight": 122, "cookies": false, "type": "", "demo": "projects\/update-sms-template.md", @@ -30647,7 +30648,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 135, + "weight": 124, "cookies": false, "type": "", "demo": "projects\/delete-sms-template.md", @@ -30935,7 +30936,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 113, + "weight": 102, "cookies": false, "type": "", "demo": "projects\/list-webhooks.md", @@ -31005,7 +31006,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 112, + "weight": 101, "cookies": false, "type": "", "demo": "projects\/create-webhook.md", @@ -31121,7 +31122,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 114, + "weight": 103, "cookies": false, "type": "", "demo": "projects\/get-webhook.md", @@ -31190,7 +31191,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 115, + "weight": 104, "cookies": false, "type": "", "demo": "projects\/update-webhook.md", @@ -31307,7 +31308,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 117, + "weight": 106, "cookies": false, "type": "", "demo": "projects\/delete-webhook.md", @@ -31378,7 +31379,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 116, + "weight": 105, "cookies": false, "type": "", "demo": "projects\/update-webhook-signature.md", @@ -43082,7 +43083,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -43171,7 +43172,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -43258,7 +43259,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -43322,7 +43323,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -43398,7 +43399,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -43464,7 +43465,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 157, + "weight": 146, "cookies": false, "type": "", "demo": "teams\/list-logs.md", @@ -43549,7 +43550,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -43648,7 +43649,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -43768,7 +43769,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -43842,7 +43843,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -43938,7 +43939,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -44014,7 +44015,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -44113,7 +44114,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -44175,7 +44176,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -44633,7 +44634,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -44719,7 +44720,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -44811,7 +44812,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -44898,7 +44899,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -44985,7 +44986,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -45066,7 +45067,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -45129,7 +45130,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -45216,7 +45217,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -45303,7 +45304,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -45420,7 +45421,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -45525,7 +45526,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -45632,7 +45633,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 189, "cookies": false, "type": "", "demo": "users\/get-usage.md", @@ -45705,7 +45706,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -45759,7 +45760,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -45822,7 +45823,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -45904,7 +45905,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -45988,7 +45989,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -46073,7 +46074,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -46160,7 +46161,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -46258,7 +46259,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -46393,7 +46394,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -46529,7 +46530,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -46648,7 +46649,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -46765,7 +46766,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -46882,7 +46883,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -47001,7 +47002,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -47083,7 +47084,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -47165,7 +47166,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -47247,7 +47248,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -47308,7 +47309,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -47390,7 +47391,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -47462,7 +47463,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -47516,7 +47517,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -47572,7 +47573,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -47645,7 +47646,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -47727,7 +47728,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -47812,7 +47813,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -47923,7 +47924,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -47994,7 +47995,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -48084,7 +48085,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -48157,7 +48158,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -48241,7 +48242,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -48323,7 +48324,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -48405,7 +48406,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 204, + "weight": 193, "cookies": false, "type": "", "demo": "vcs\/create-repository-detection.md", @@ -48502,7 +48503,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 205, + "weight": 194, "cookies": false, "type": "", "demo": "vcs\/list-repositories.md", @@ -48601,7 +48602,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 206, + "weight": 195, "cookies": false, "type": "", "demo": "vcs\/create-repository.md", @@ -48687,7 +48688,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 207, + "weight": 196, "cookies": false, "type": "", "demo": "vcs\/get-repository.md", @@ -48758,7 +48759,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 208, + "weight": 197, "cookies": false, "type": "", "demo": "vcs\/list-repository-branches.md", @@ -48829,7 +48830,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 203, + "weight": 192, "cookies": false, "type": "", "demo": "vcs\/get-repository-contents.md", @@ -48915,7 +48916,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 213, + "weight": 202, "cookies": false, "type": "", "demo": "vcs\/update-external-deployments.md", @@ -49005,7 +49006,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 210, + "weight": 199, "cookies": false, "type": "", "demo": "vcs\/list-installations.md", @@ -49091,7 +49092,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 211, + "weight": 200, "cookies": false, "type": "", "demo": "vcs\/get-installation.md", @@ -49143,7 +49144,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 212, + "weight": 201, "cookies": false, "type": "", "demo": "vcs\/delete-installation.md", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 70e8b895ce..076d8e837a 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -558,7 +558,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -631,7 +631,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -758,7 +758,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -901,7 +901,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1028,7 +1028,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1165,7 +1165,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1306,7 +1306,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1410,7 +1410,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1512,7 +1512,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1614,7 +1614,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -3747,7 +3747,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -3877,7 +3877,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4013,7 +4013,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4075,7 +4075,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4567,7 +4567,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4653,7 +4653,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -4749,7 +4749,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -4845,7 +4845,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -14876,7 +14876,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -14932,7 +14932,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -14988,7 +14988,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -15040,7 +15040,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -15092,7 +15092,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -15144,7 +15144,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -15207,7 +15207,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -15259,7 +15259,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -15311,7 +15311,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -15376,7 +15376,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -15441,7 +15441,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -15517,7 +15517,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -15582,7 +15582,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -15627,6 +15627,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -15673,7 +15674,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -15738,7 +15739,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -15803,7 +15804,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -15868,7 +15869,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -15933,7 +15934,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -15998,7 +15999,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -16063,7 +16064,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -16128,7 +16129,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -16193,7 +16194,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -16245,7 +16246,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -16297,7 +16298,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -16349,7 +16350,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -16405,7 +16406,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -16461,7 +16462,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -16517,7 +16518,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -16573,7 +16574,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -16629,7 +16630,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -16685,7 +16686,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -16741,7 +16742,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -16797,7 +16798,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -16886,7 +16887,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -17033,7 +17034,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -17192,7 +17193,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -17370,7 +17371,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -17568,7 +17569,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -17752,7 +17753,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -17942,7 +17943,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -17997,7 +17998,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -18061,7 +18062,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -18149,7 +18150,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -18237,7 +18238,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -18326,7 +18327,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -18508,7 +18509,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -18692,7 +18693,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -18847,7 +18848,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -19003,7 +19004,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -19122,7 +19123,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -19244,7 +19245,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -19342,7 +19343,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -19443,7 +19444,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -19551,7 +19552,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -19662,7 +19663,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -19770,7 +19771,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -19881,7 +19882,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -20115,7 +20116,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -20349,7 +20350,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -20447,7 +20448,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -20548,7 +20549,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -20646,7 +20647,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -20747,7 +20748,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -20845,7 +20846,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -20946,7 +20947,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -21044,7 +21045,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -21145,7 +21146,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -21200,7 +21201,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -21264,7 +21265,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -21352,7 +21353,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -21440,7 +21441,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -21527,7 +21528,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -21612,7 +21613,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -21674,7 +21675,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -21755,7 +21756,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -21819,7 +21820,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -21907,7 +21908,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -22004,7 +22005,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -22097,7 +22098,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -22162,7 +22163,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -32415,7 +32416,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -32506,7 +32507,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -32595,7 +32596,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -32661,7 +32662,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -32739,7 +32740,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -32807,7 +32808,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -32908,7 +32909,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -33030,7 +33031,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -33106,7 +33107,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -33204,7 +33205,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -33282,7 +33283,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -33383,7 +33384,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -33447,7 +33448,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -33912,7 +33913,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -33999,7 +34000,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -34092,7 +34093,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -34180,7 +34181,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -34268,7 +34269,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -34350,7 +34351,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -34414,7 +34415,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -34502,7 +34503,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -34590,7 +34591,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -34708,7 +34709,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -34814,7 +34815,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -34922,7 +34923,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -34977,7 +34978,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -35041,7 +35042,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -35124,7 +35125,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -35209,7 +35210,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -35295,7 +35296,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -35383,7 +35384,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -35482,7 +35483,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -35620,7 +35621,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -35759,7 +35760,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -35881,7 +35882,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -36001,7 +36002,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -36121,7 +36122,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -36243,7 +36244,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -36326,7 +36327,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -36409,7 +36410,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -36492,7 +36493,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -36554,7 +36555,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -36637,7 +36638,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -36710,7 +36711,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -36765,7 +36766,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -36822,7 +36823,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -36896,7 +36897,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -36979,7 +36980,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -37065,7 +37066,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -37177,7 +37178,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -37249,7 +37250,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -37340,7 +37341,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -37414,7 +37415,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -37499,7 +37500,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -37582,7 +37583,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 07889bba5e..eeeb2eeea8 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -608,7 +608,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -683,7 +683,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -807,7 +807,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -948,7 +948,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1072,7 +1072,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1209,7 +1209,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1349,7 +1349,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1450,7 +1450,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1551,7 +1551,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1652,7 +1652,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -4191,7 +4191,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4317,7 +4317,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4449,7 +4449,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4513,7 +4513,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -5001,7 +5001,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -5085,7 +5085,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5177,7 +5177,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5269,7 +5269,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -7649,7 +7649,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -7724,7 +7724,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -7797,7 +7797,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -7850,7 +7850,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -7903,7 +7903,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -7956,7 +7956,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -8009,7 +8009,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -8062,7 +8062,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -8115,7 +8115,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -8168,7 +8168,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -8223,7 +8223,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -8308,7 +8308,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -10559,7 +10559,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -10644,7 +10644,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -10735,7 +10735,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -10798,7 +10798,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -10874,7 +10874,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -10937,7 +10937,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -11030,7 +11030,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -11151,7 +11151,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -11222,7 +11222,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -11316,7 +11316,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -11389,7 +11389,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -11485,7 +11485,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -11548,7 +11548,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 4b384cae76..38928664f8 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -657,7 +657,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -731,7 +731,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -854,7 +854,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -994,7 +994,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1117,7 +1117,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1253,7 +1253,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1392,7 +1392,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1492,7 +1492,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1592,7 +1592,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1692,7 +1692,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -4200,7 +4200,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4326,7 +4326,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4458,7 +4458,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4522,7 +4522,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -5010,7 +5010,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -5094,7 +5094,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5186,7 +5186,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5278,7 +5278,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -16160,7 +16160,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -16235,7 +16235,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -16308,7 +16308,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -16359,7 +16359,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -16410,7 +16410,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -16461,7 +16461,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -16521,7 +16521,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -16572,7 +16572,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -16623,7 +16623,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -16685,7 +16685,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -16747,7 +16747,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -16818,7 +16818,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -16880,7 +16880,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -16923,6 +16923,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -16966,7 +16967,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -17028,7 +17029,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -17090,7 +17091,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -17152,7 +17153,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -17214,7 +17215,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -17276,7 +17277,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -17338,7 +17339,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -17400,7 +17401,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -17462,7 +17463,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -17513,7 +17514,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -17564,7 +17565,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -17615,7 +17616,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -17668,7 +17669,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -17721,7 +17722,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -17774,7 +17775,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -17827,7 +17828,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -17880,7 +17881,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -17933,7 +17934,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -17986,7 +17987,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -18039,7 +18040,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -18124,7 +18125,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -18284,7 +18285,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -18451,7 +18452,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -18649,7 +18650,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -18862,7 +18863,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -19052,7 +19053,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -19241,7 +19242,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -19297,7 +19298,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -19358,7 +19359,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -19440,7 +19441,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -19522,7 +19523,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -19607,7 +19608,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -19796,7 +19797,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -19982,7 +19983,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -20140,7 +20141,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -20294,7 +20295,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -20424,7 +20425,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -20552,7 +20553,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -20657,7 +20658,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -20760,7 +20761,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -20877,7 +20878,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -20992,7 +20993,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -21109,7 +21110,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -21224,7 +21225,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -21471,7 +21472,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -21713,7 +21714,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -21818,7 +21819,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -21921,7 +21922,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -22026,7 +22027,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -22129,7 +22130,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -22234,7 +22235,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -22337,7 +22338,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -22442,7 +22443,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -22543,7 +22544,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -22599,7 +22600,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -22660,7 +22661,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -22742,7 +22743,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -22824,7 +22825,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -22907,7 +22908,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -22996,7 +22997,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -23057,7 +23058,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -23139,7 +23140,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -23200,7 +23201,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -23282,7 +23283,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -23373,7 +23374,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -23461,7 +23462,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -23525,7 +23526,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -23596,7 +23597,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 232, + "weight": 221, "cookies": false, "type": "", "demo": "migrations\/list.md", @@ -23679,7 +23680,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 226, + "weight": 215, "cookies": false, "type": "", "demo": "migrations\/create-appwrite-migration.md", @@ -23792,7 +23793,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 234, + "weight": 223, "cookies": false, "type": "", "demo": "migrations\/get-appwrite-report.md", @@ -23901,7 +23902,7 @@ "x-appwrite": { "method": "createCSVExport", "group": null, - "weight": 231, + "weight": 220, "cookies": false, "type": "", "demo": "migrations\/create-csv-export.md", @@ -24027,7 +24028,7 @@ "x-appwrite": { "method": "createCSVImport", "group": null, - "weight": 230, + "weight": 219, "cookies": false, "type": "", "demo": "migrations\/create-csv-import.md", @@ -24118,7 +24119,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 227, + "weight": 216, "cookies": false, "type": "", "demo": "migrations\/create-firebase-migration.md", @@ -24211,7 +24212,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 235, + "weight": 224, "cookies": false, "type": "", "demo": "migrations\/get-firebase-report.md", @@ -24297,7 +24298,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 229, + "weight": 218, "cookies": false, "type": "", "demo": "migrations\/create-n-host-migration.md", @@ -24432,7 +24433,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 237, + "weight": 226, "cookies": false, "type": "", "demo": "migrations\/get-n-host-report.md", @@ -24568,7 +24569,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 228, + "weight": 217, "cookies": false, "type": "", "demo": "migrations\/create-supabase-migration.md", @@ -24696,7 +24697,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 236, + "weight": 225, "cookies": false, "type": "", "demo": "migrations\/get-supabase-report.md", @@ -24823,7 +24824,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 233, + "weight": 222, "cookies": false, "type": "", "demo": "migrations\/get.md", @@ -24882,7 +24883,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 238, + "weight": 227, "cookies": false, "type": "", "demo": "migrations\/retry.md", @@ -24936,7 +24937,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 239, + "weight": 228, "cookies": false, "type": "", "demo": "migrations\/delete.md", @@ -24995,7 +24996,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 138, + "weight": 127, "cookies": false, "type": "", "demo": "project\/get-usage.md", @@ -25078,7 +25079,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 140, + "weight": 129, "cookies": false, "type": "", "demo": "project\/list-variables.md", @@ -25127,7 +25128,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 139, + "weight": 128, "cookies": false, "type": "", "demo": "project\/create-variable.md", @@ -25209,7 +25210,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 141, + "weight": 130, "cookies": false, "type": "", "demo": "project\/get-variable.md", @@ -25268,7 +25269,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 142, + "weight": 131, "cookies": false, "type": "", "demo": "project\/update-variable.md", @@ -25354,7 +25355,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 143, + "weight": 132, "cookies": false, "type": "", "demo": "project\/delete-variable.md", @@ -25438,7 +25439,7 @@ "parameters": [ { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search", "required": false, "type": "array", "collectionFormat": "multi", @@ -25493,7 +25494,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 92, + "weight": 81, "cookies": false, "type": "", "demo": "projects\/create.md", @@ -25641,7 +25642,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 93, + "weight": 82, "cookies": false, "type": "", "demo": "projects\/get.md", @@ -25700,7 +25701,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 94, + "weight": 83, "cookies": false, "type": "", "demo": "projects\/update.md", @@ -25826,7 +25827,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 111, + "weight": 100, "cookies": false, "type": "", "demo": "projects\/delete.md", @@ -25887,7 +25888,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 98, + "weight": 87, "cookies": false, "type": "", "demo": "projects\/update-api-status.md", @@ -26044,7 +26045,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 99, + "weight": 88, "cookies": false, "type": "", "demo": "projects\/update-api-status-all.md", @@ -26183,7 +26184,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 104, + "weight": 93, "cookies": false, "type": "", "demo": "projects\/update-auth-duration.md", @@ -26262,7 +26263,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 103, + "weight": 92, "cookies": false, "type": "", "demo": "projects\/update-auth-limit.md", @@ -26341,7 +26342,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 109, + "weight": 98, "cookies": false, "type": "", "demo": "projects\/update-auth-sessions-limit.md", @@ -26420,7 +26421,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 102, + "weight": 91, "cookies": false, "type": "", "demo": "projects\/update-memberships-privacy.md", @@ -26513,7 +26514,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 110, + "weight": 99, "cookies": false, "type": "", "demo": "projects\/update-mock-numbers.md", @@ -26595,7 +26596,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 107, + "weight": 96, "cookies": false, "type": "", "demo": "projects\/update-auth-password-dictionary.md", @@ -26674,7 +26675,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 106, + "weight": 95, "cookies": false, "type": "", "demo": "projects\/update-auth-password-history.md", @@ -26753,7 +26754,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 108, + "weight": 97, "cookies": false, "type": "", "demo": "projects\/update-personal-data-check.md", @@ -26832,7 +26833,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 101, + "weight": 90, "cookies": false, "type": "", "demo": "projects\/update-session-alerts.md", @@ -26911,7 +26912,7 @@ "x-appwrite": { "method": "updateSessionInvalidation", "group": "auth", - "weight": 137, + "weight": 126, "cookies": false, "type": "", "demo": "projects\/update-session-invalidation.md", @@ -26990,7 +26991,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 105, + "weight": 94, "cookies": false, "type": "", "demo": "projects\/update-auth-status.md", @@ -27459,7 +27460,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 123, + "weight": 112, "cookies": false, "type": "", "demo": "projects\/create-jwt.md", @@ -27604,7 +27605,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 119, + "weight": 108, "cookies": false, "type": "", "demo": "projects\/list-keys.md", @@ -27672,7 +27673,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 118, + "weight": 107, "cookies": false, "type": "", "demo": "projects\/create-key.md", @@ -27826,7 +27827,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 120, + "weight": 109, "cookies": false, "type": "", "demo": "projects\/get-key.md", @@ -27893,7 +27894,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 121, + "weight": 110, "cookies": false, "type": "", "demo": "projects\/update-key.md", @@ -28050,7 +28051,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 122, + "weight": 111, "cookies": false, "type": "", "demo": "projects\/delete-key.md", @@ -28200,7 +28201,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 100, + "weight": 89, "cookies": false, "type": "", "demo": "projects\/update-o-auth-2.md", @@ -28343,7 +28344,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 125, + "weight": 114, "cookies": false, "type": "", "demo": "projects\/list-platforms.md", @@ -28411,7 +28412,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 124, + "weight": 113, "cookies": false, "type": "", "demo": "projects\/create-platform.md", @@ -28532,7 +28533,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 126, + "weight": 115, "cookies": false, "type": "", "demo": "projects\/get-platform.md", @@ -28599,7 +28600,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 127, + "weight": 116, "cookies": false, "type": "", "demo": "projects\/update-platform.md", @@ -28697,7 +28698,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 128, + "weight": 117, "cookies": false, "type": "", "demo": "projects\/delete-platform.md", @@ -28766,7 +28767,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 96, + "weight": 85, "cookies": false, "type": "", "demo": "projects\/update-service-status.md", @@ -28869,7 +28870,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 97, + "weight": 86, "cookies": false, "type": "", "demo": "projects\/update-service-status-all.md", @@ -28948,7 +28949,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 129, + "weight": 118, "cookies": false, "type": "", "demo": "projects\/update-smtp.md", @@ -29154,7 +29155,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 130, + "weight": 119, "cookies": false, "type": "", "demo": "projects\/create-smtp-test.md", @@ -29373,7 +29374,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 95, + "weight": 84, "cookies": false, "type": "", "demo": "projects\/update-team.md", @@ -29450,7 +29451,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 132, + "weight": 121, "cookies": false, "type": "", "demo": "projects\/get-email-template.md", @@ -29671,7 +29672,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 134, + "weight": 123, "cookies": false, "type": "", "demo": "projects\/update-email-template.md", @@ -29935,7 +29936,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 136, + "weight": 125, "cookies": false, "type": "", "demo": "projects\/delete-email-template.md", @@ -30156,7 +30157,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 131, + "weight": 120, "cookies": false, "type": "", "demo": "projects\/get-sms-template.md", @@ -30438,7 +30439,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 133, + "weight": 122, "cookies": false, "type": "", "demo": "projects\/update-sms-template.md", @@ -30742,7 +30743,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 135, + "weight": 124, "cookies": false, "type": "", "demo": "projects\/delete-sms-template.md", @@ -31024,7 +31025,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 113, + "weight": 102, "cookies": false, "type": "", "demo": "projects\/list-webhooks.md", @@ -31092,7 +31093,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 112, + "weight": 101, "cookies": false, "type": "", "demo": "projects\/create-webhook.md", @@ -31211,7 +31212,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 114, + "weight": 103, "cookies": false, "type": "", "demo": "projects\/get-webhook.md", @@ -31278,7 +31279,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 115, + "weight": 104, "cookies": false, "type": "", "demo": "projects\/update-webhook.md", @@ -31400,7 +31401,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 117, + "weight": 106, "cookies": false, "type": "", "demo": "projects\/delete-webhook.md", @@ -31469,7 +31470,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 116, + "weight": 105, "cookies": false, "type": "", "demo": "projects\/update-webhook-signature.md", @@ -42953,7 +42954,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -43038,7 +43039,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -43129,7 +43130,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -43192,7 +43193,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -43268,7 +43269,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -43331,7 +43332,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 157, + "weight": 146, "cookies": false, "type": "", "demo": "teams\/list-logs.md", @@ -43411,7 +43412,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -43504,7 +43505,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -43625,7 +43626,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -43696,7 +43697,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -43790,7 +43791,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -43863,7 +43864,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -43958,7 +43959,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -44020,7 +44021,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -44464,7 +44465,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -44547,7 +44548,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -44646,7 +44647,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -44739,7 +44740,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -44830,7 +44831,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -44910,7 +44911,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -44973,7 +44974,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -45066,7 +45067,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -45159,7 +45160,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -45287,7 +45288,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -45401,7 +45402,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -45513,7 +45514,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 189, "cookies": false, "type": "", "demo": "users\/get-usage.md", @@ -45584,7 +45585,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -45640,7 +45641,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -45703,7 +45704,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -45784,7 +45785,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -45868,7 +45869,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -45950,7 +45951,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -46032,7 +46033,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -46125,7 +46126,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -46261,7 +46262,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -46393,7 +46394,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -46510,7 +46511,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -46627,7 +46628,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -46744,7 +46745,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -46863,7 +46864,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -46944,7 +46945,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -47025,7 +47026,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -47104,7 +47105,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -47165,7 +47166,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -47244,7 +47245,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -47314,7 +47315,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -47370,7 +47371,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -47428,7 +47429,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -47499,7 +47500,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -47578,7 +47579,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -47660,7 +47661,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -47772,7 +47773,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -47841,7 +47842,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -47932,7 +47933,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -48003,7 +48004,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -48087,7 +48088,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -48168,7 +48169,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -48249,7 +48250,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 204, + "weight": 193, "cookies": false, "type": "", "demo": "vcs\/create-repository-detection.md", @@ -48345,7 +48346,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 205, + "weight": 194, "cookies": false, "type": "", "demo": "vcs\/list-repositories.md", @@ -48439,7 +48440,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 206, + "weight": 195, "cookies": false, "type": "", "demo": "vcs\/create-repository.md", @@ -48523,7 +48524,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 207, + "weight": 196, "cookies": false, "type": "", "demo": "vcs\/get-repository.md", @@ -48590,7 +48591,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 208, + "weight": 197, "cookies": false, "type": "", "demo": "vcs\/list-repository-branches.md", @@ -48657,7 +48658,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 203, + "weight": 192, "cookies": false, "type": "", "demo": "vcs\/get-repository-contents.md", @@ -48741,7 +48742,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 213, + "weight": 202, "cookies": false, "type": "", "demo": "vcs\/update-external-deployments.md", @@ -48826,7 +48827,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 210, + "weight": 199, "cookies": false, "type": "", "demo": "vcs\/list-installations.md", @@ -48907,7 +48908,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 211, + "weight": 200, "cookies": false, "type": "", "demo": "vcs\/get-installation.md", @@ -48961,7 +48962,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 212, + "weight": 201, "cookies": false, "type": "", "demo": "vcs\/delete-installation.md", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 63e43dbf69..40e13396fc 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -624,7 +624,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -700,7 +700,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -827,7 +827,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -971,7 +971,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1098,7 +1098,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1238,7 +1238,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1381,7 +1381,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1485,7 +1485,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1589,7 +1589,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1693,7 +1693,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -3905,7 +3905,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4033,7 +4033,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4167,7 +4167,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4233,7 +4233,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4723,7 +4723,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4809,7 +4809,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -4903,7 +4903,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -4997,7 +4997,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -14832,7 +14832,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -14909,7 +14909,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -14984,7 +14984,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -15036,7 +15036,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -15088,7 +15088,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -15140,7 +15140,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -15201,7 +15201,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -15253,7 +15253,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -15305,7 +15305,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -15368,7 +15368,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -15431,7 +15431,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -15503,7 +15503,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -15566,7 +15566,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -15610,6 +15610,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -15653,7 +15654,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -15716,7 +15717,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -15779,7 +15780,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -15842,7 +15843,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -15905,7 +15906,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -15968,7 +15969,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -16031,7 +16032,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -16094,7 +16095,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -16157,7 +16158,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -16209,7 +16210,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -16261,7 +16262,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -16313,7 +16314,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -16368,7 +16369,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -16423,7 +16424,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -16478,7 +16479,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -16533,7 +16534,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -16588,7 +16589,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -16643,7 +16644,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -16698,7 +16699,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -16753,7 +16754,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -16839,7 +16840,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -17000,7 +17001,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -17168,7 +17169,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -17367,7 +17368,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -17581,7 +17582,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -17774,7 +17775,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -17966,7 +17967,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -18023,7 +18024,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -18085,7 +18086,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -18168,7 +18169,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -18251,7 +18252,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -18337,7 +18338,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -18529,7 +18530,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -18718,7 +18719,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -18879,7 +18880,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -19036,7 +19037,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -19167,7 +19168,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -19296,7 +19297,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -19402,7 +19403,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -19506,7 +19507,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -19624,7 +19625,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -19740,7 +19741,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -19858,7 +19859,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -19974,7 +19975,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -20224,7 +20225,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -20469,7 +20470,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -20575,7 +20576,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -20679,7 +20680,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -20785,7 +20786,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -20889,7 +20890,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -20995,7 +20996,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -21099,7 +21100,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -21205,7 +21206,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -21307,7 +21308,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -21364,7 +21365,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -21426,7 +21427,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -21509,7 +21510,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -21592,7 +21593,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -21676,7 +21677,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -21766,7 +21767,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -21828,7 +21829,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -21911,7 +21912,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -21973,7 +21974,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -22056,7 +22057,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -22148,7 +22149,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -22238,7 +22239,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -22303,7 +22304,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -32364,7 +32365,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -32451,7 +32452,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -32544,7 +32545,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -32609,7 +32610,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -32687,7 +32688,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -32752,7 +32753,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -32847,7 +32848,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -32970,7 +32971,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -33043,7 +33044,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -33139,7 +33140,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -33214,7 +33215,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -33311,7 +33312,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -33375,7 +33376,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -33826,7 +33827,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -33910,7 +33911,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -34010,7 +34011,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -34104,7 +34105,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -34196,7 +34197,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -34277,7 +34278,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -34341,7 +34342,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -34435,7 +34436,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -34529,7 +34530,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -34658,7 +34659,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -34773,7 +34774,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -34886,7 +34887,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -34943,7 +34944,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -35007,7 +35008,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -35089,7 +35090,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -35174,7 +35175,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -35257,7 +35258,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -35340,7 +35341,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -35434,7 +35435,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -35573,7 +35574,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -35708,7 +35709,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -35828,7 +35829,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -35948,7 +35949,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -36068,7 +36069,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -36190,7 +36191,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -36272,7 +36273,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -36354,7 +36355,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -36434,7 +36435,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -36496,7 +36497,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -36576,7 +36577,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -36647,7 +36648,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -36704,7 +36705,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -36763,7 +36764,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -36835,7 +36836,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -36915,7 +36916,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -36998,7 +36999,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -37111,7 +37112,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -37181,7 +37182,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -37273,7 +37274,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -37345,7 +37346,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -37430,7 +37431,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -37512,7 +37513,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 834c926977..3be014dfc5 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 20.3.3 + +* Fix boolean parameter not handled correctly in Client requests + ## 20.3.2 * Fix OAuth2 browser infinite redirect issue From 23d84cf29fb8c2568c8c01c07764a1c81e535de4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 13 Jan 2026 14:21:09 +0530 Subject: [PATCH 16/52] update: dart sdk. --- app/config/sdks.php | 2 +- docs/sdks/dart/CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/config/sdks.php b/app/config/sdks.php index eee8f03b70..5d7755e38f 100644 --- a/app/config/sdks.php +++ b/app/config/sdks.php @@ -377,7 +377,7 @@ return [ [ 'key' => 'dart', 'name' => 'Dart', - 'version' => '20.1.0', + 'version' => '20.1.1', 'url' => 'https://github.com/appwrite/sdk-for-dart', 'package' => 'https://pub.dev/packages/dart_appwrite', 'enabled' => true, diff --git a/docs/sdks/dart/CHANGELOG.md b/docs/sdks/dart/CHANGELOG.md index b370394c8b..9f5ade774a 100644 --- a/docs/sdks/dart/CHANGELOG.md +++ b/docs/sdks/dart/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 20.1.1 + +* Fix boolean parameter not handled correctly in Client requests + ## 20.1.0 * Added ability to create columns and indexes synchronously while creating a table From ae6df7802074d023f5109e3a4eca20d9a3262290 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 13 Jan 2026 16:10:47 +0530 Subject: [PATCH 17/52] Add int64 format support for integer attributes This change adds int64 format specification to integer attribute min/max values in the API response models and updates all OpenAPI/Swagger specifications accordingly. This ensures proper type handling for large integer values that exceed int32 range in client SDKs. Changes: - Add 'format: int64' to min/max fields in AttributeInteger and ColumnInteger models - Regenerate OpenAPI 3.x and Swagger 2.x specs for all platforms (client, console, server) - Update composer dependencies --- app/config/specs/open-api3-1.8.x-client.json | 192 ++- app/config/specs/open-api3-1.8.x-console.json | 1446 +++++++++------- app/config/specs/open-api3-1.8.x-server.json | 746 +++++---- app/config/specs/open-api3-latest-client.json | 168 +- .../specs/open-api3-latest-console.json | 806 +++++---- app/config/specs/open-api3-latest-server.json | 588 ++++--- app/config/specs/swagger2-1.8.x-client.json | 189 ++- app/config/specs/swagger2-1.8.x-console.json | 1458 ++++++++++------- app/config/specs/swagger2-1.8.x-server.json | 737 +++++---- app/config/specs/swagger2-latest-client.json | 165 +- app/config/specs/swagger2-latest-console.json | 797 +++++---- app/config/specs/swagger2-latest-server.json | 579 ++++--- composer.lock | 70 +- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Integer/Update.php | 6 +- .../Tables/Columns/Integer/Create.php | 6 +- .../Tables/Columns/Integer/Update.php | 6 +- .../SDK/Specification/Format/OpenAPI3.php | 12 +- .../SDK/Specification/Format/Swagger2.php | 12 +- .../Response/Model/AttributeInteger.php | 2 + .../Utopia/Response/Model/ColumnInteger.php | 2 + 21 files changed, 4687 insertions(+), 3306 deletions(-) diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json index 052fe536c9..4bb90a535f 100644 --- a/app/config/specs/open-api3-1.8.x-client.json +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.8.0", + "version": "1.8.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -140,7 +140,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -224,12 +225,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -439,7 +442,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -551,7 +555,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -623,7 +627,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -747,7 +751,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -887,7 +891,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1011,7 +1015,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1145,7 +1149,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1283,7 +1287,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1384,7 +1388,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1483,7 +1487,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1582,7 +1586,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1796,7 +1800,8 @@ "oldPassword": { "type": "string", "description": "Current user password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1868,12 +1873,14 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2072,12 +2079,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2382,12 +2391,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3304,7 +3315,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3390,12 +3402,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3621,7 +3635,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3746,7 +3761,8 @@ "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4039,7 +4055,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4167,7 +4183,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4301,7 +4317,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4361,7 +4377,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4851,7 +4867,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4935,7 +4951,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5029,7 +5045,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5123,7 +5139,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -5980,7 +5996,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7146,12 +7163,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7273,12 +7292,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7318,7 +7339,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 454, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -7405,7 +7426,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 452, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -7523,7 +7544,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 453, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -7598,7 +7619,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -7652,7 +7673,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -7706,7 +7727,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -7760,7 +7781,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -7814,7 +7835,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -7868,7 +7889,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -7922,7 +7943,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -7976,7 +7997,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -8030,7 +8051,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -8084,7 +8105,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -8138,7 +8159,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -8222,7 +8243,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -8298,7 +8319,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 525, + "weight": 526, "cookies": false, "type": "", "demo": "storage\/list-files.md", @@ -8397,7 +8418,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 523, + "weight": 524, "cookies": false, "type": "upload", "demo": "storage\/create-file.md", @@ -8452,7 +8473,8 @@ "file": { "type": "string", "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", - "x-example": null + "x-example": null, + "format": "binary" }, "permissions": { "type": "array", @@ -8498,7 +8520,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 524, + "weight": 525, "cookies": false, "type": "", "demo": "storage\/get-file.md", @@ -8572,7 +8594,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 526, + "weight": 527, "cookies": false, "type": "", "demo": "storage\/update-file.md", @@ -8664,7 +8686,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 527, + "weight": 528, "cookies": false, "type": "", "demo": "storage\/delete-file.md", @@ -8733,7 +8755,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 529, + "weight": 530, "cookies": false, "type": "location", "demo": "storage\/get-file-download.md", @@ -8813,7 +8835,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 528, + "weight": 529, "cookies": false, "type": "location", "demo": "storage\/get-file-preview.md", @@ -9043,7 +9065,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 530, + "weight": 531, "cookies": false, "type": "location", "demo": "storage\/get-file-view.md", @@ -9240,7 +9262,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -10403,12 +10426,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10529,12 +10554,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10574,7 +10601,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -10663,7 +10690,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -10750,7 +10777,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -10814,7 +10841,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -10890,7 +10917,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -10956,7 +10983,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -11055,7 +11082,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -11104,7 +11131,8 @@ "email": { "type": "string", "description": "Email of the new team member.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -11114,7 +11142,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -11134,7 +11163,8 @@ "url": { "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -11175,7 +11205,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -11249,7 +11279,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -11345,7 +11375,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -11421,7 +11451,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -11521,7 +11551,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -11584,7 +11614,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index de68c4db48..22f247843f 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.8.0", + "version": "1.8.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -138,7 +138,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -261,12 +262,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -473,7 +476,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -584,7 +588,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -655,7 +659,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -778,7 +782,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -917,7 +921,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1040,7 +1044,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1173,7 +1177,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1310,7 +1314,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1410,7 +1414,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1508,7 +1512,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1606,7 +1610,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1817,7 +1821,8 @@ "oldPassword": { "type": "string", "description": "Current user password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1888,12 +1893,14 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2089,12 +2096,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2394,12 +2403,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3304,7 +3315,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3389,12 +3401,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3618,7 +3632,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3742,7 +3757,8 @@ "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4032,7 +4048,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4160,7 +4176,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4294,7 +4310,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4354,7 +4370,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4844,7 +4860,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4928,7 +4944,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5022,7 +5038,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5116,7 +5132,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -5862,7 +5878,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 495, + "weight": 496, "cookies": false, "type": "", "demo": "assistant\/chat.md", @@ -5923,7 +5939,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 497, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -5998,7 +6014,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 494, + "weight": 495, "cookies": false, "type": "", "demo": "console\/variables.md", @@ -6387,7 +6403,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -8239,6 +8256,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -8356,6 +8374,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8719,18 +8738,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8848,18 +8870,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -8974,18 +8999,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -9103,18 +9131,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -10310,7 +10341,8 @@ "size": { "type": "integer", "description": "Attribute size for text attributes, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -10450,6 +10482,7 @@ "type": "integer", "description": "Maximum size of the string attribute.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10564,6 +10597,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10681,6 +10715,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -12346,12 +12381,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12473,12 +12510,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -13331,7 +13370,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -13416,7 +13455,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 435, + "weight": 436, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -13556,7 +13595,8 @@ "timeout": { "type": "integer", "description": "Function maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13711,7 +13751,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -13761,7 +13801,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 441, + "weight": 442, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -13811,7 +13851,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 464, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/list-templates.md", @@ -14003,7 +14043,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 463, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/get-template.md", @@ -14063,7 +14103,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 457, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/list-usage.md", @@ -14135,7 +14175,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -14195,7 +14235,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -14342,7 +14382,8 @@ "timeout": { "type": "integer", "description": "Maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -14487,7 +14528,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -14549,7 +14590,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 444, + "weight": 445, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -14630,7 +14671,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 445, + "weight": 446, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -14725,7 +14766,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 442, + "weight": 443, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -14782,7 +14823,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -14824,7 +14866,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 450, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -14910,7 +14952,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 447, + "weight": 448, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -15027,7 +15069,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 448, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -15125,7 +15167,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 443, + "weight": 444, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -15188,7 +15230,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 446, + "weight": 447, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -15253,7 +15295,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 449, + "weight": 450, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -15344,7 +15386,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 451, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -15416,7 +15458,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 454, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -15503,7 +15545,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 452, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -15621,7 +15663,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 453, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -15687,7 +15729,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 455, + "weight": 456, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -15759,7 +15801,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 456, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-usage.md", @@ -15841,7 +15883,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 460, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -15901,7 +15943,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 458, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -15993,7 +16035,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 459, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -16063,7 +16105,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 461, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -16157,7 +16199,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 462, + "weight": 463, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -16229,7 +16271,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -16283,7 +16325,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -16337,7 +16379,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -16388,7 +16430,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -16439,7 +16481,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -16490,7 +16532,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -16552,7 +16594,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -16603,7 +16645,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -16654,7 +16696,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -16718,7 +16760,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -16782,7 +16824,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -16857,7 +16899,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -16921,7 +16963,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -16965,6 +17007,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -17011,7 +17054,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -17075,7 +17118,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -17139,7 +17182,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -17203,7 +17246,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -17267,7 +17310,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -17331,7 +17374,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -17395,7 +17438,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -17459,7 +17502,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -17523,7 +17566,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -17574,7 +17617,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -17625,7 +17668,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -17676,7 +17719,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -17730,7 +17773,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -17784,7 +17827,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -17838,7 +17881,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -17892,7 +17935,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -17946,7 +17989,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -18000,7 +18043,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -18054,7 +18097,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -18108,7 +18151,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -18196,7 +18239,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -18342,7 +18385,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -18500,7 +18543,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -18609,7 +18652,8 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -18677,7 +18721,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -18805,6 +18849,7 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS platforms.", "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -18874,7 +18919,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -19055,7 +19100,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -19242,7 +19287,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -19296,7 +19341,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -19359,7 +19404,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -19446,7 +19491,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -19533,7 +19578,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -19621,7 +19666,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -19800,7 +19845,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -19981,7 +20026,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -20133,7 +20178,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -20286,7 +20331,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -20351,7 +20396,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20361,7 +20407,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20404,7 +20451,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -20482,7 +20529,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20525,7 +20573,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -20622,7 +20670,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -20722,7 +20770,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -20776,7 +20824,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20786,7 +20835,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20829,7 +20879,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -20896,7 +20946,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20939,7 +20990,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -20993,7 +21044,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21003,7 +21055,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21046,7 +21099,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -21113,7 +21166,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21156,7 +21210,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -21291,7 +21345,8 @@ "port": { "type": "integer", "description": "The default SMTP server port.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -21333,7 +21388,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21343,7 +21399,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21387,7 +21444,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -21526,6 +21583,7 @@ "type": "integer", "description": "SMTP port.", "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -21569,7 +21627,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21618,7 +21677,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -21662,7 +21721,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -21715,7 +21775,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -21815,7 +21875,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -21859,7 +21919,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -21912,7 +21973,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -22012,7 +22073,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -22056,7 +22117,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -22109,7 +22171,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -22209,7 +22271,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -22253,7 +22315,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -22306,7 +22369,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -22406,7 +22469,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -22460,7 +22523,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -22523,7 +22586,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -22610,7 +22673,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -22697,7 +22760,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -22783,7 +22846,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -22867,7 +22930,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -22928,7 +22991,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -23008,7 +23071,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -23071,7 +23134,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -23158,7 +23221,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -23254,7 +23317,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -23345,7 +23408,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -23409,7 +23472,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -23485,7 +23548,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 232, + "weight": 221, "cookies": false, "type": "", "demo": "migrations\/list.md", @@ -23571,7 +23634,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 226, + "weight": 215, "cookies": false, "type": "", "demo": "migrations\/create-appwrite-migration.md", @@ -23631,7 +23694,8 @@ "endpoint": { "type": "string", "description": "Source Appwrite endpoint", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "projectId": { "type": "string", @@ -23680,7 +23744,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 234, + "weight": 223, "cookies": false, "type": "", "demo": "migrations\/get-appwrite-report.md", @@ -23794,7 +23858,7 @@ "x-appwrite": { "method": "createCSVExport", "group": null, - "weight": 231, + "weight": 220, "cookies": false, "type": "", "demo": "migrations\/create-csv-export.md", @@ -23909,7 +23973,7 @@ "x-appwrite": { "method": "createCSVImport", "group": null, - "weight": 230, + "weight": 219, "cookies": false, "type": "", "demo": "migrations\/create-csv-import.md", @@ -23994,7 +24058,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 227, + "weight": 216, "cookies": false, "type": "", "demo": "migrations\/create-firebase-migration.md", @@ -24085,7 +24149,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 235, + "weight": 224, "cookies": false, "type": "", "demo": "migrations\/get-firebase-report.md", @@ -24172,7 +24236,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 229, + "weight": 218, "cookies": false, "type": "", "demo": "migrations\/create-n-host-migration.md", @@ -24257,7 +24321,8 @@ "port": { "type": "integer", "description": "Source's Database Port", - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24299,7 +24364,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 237, + "weight": 226, "cookies": false, "type": "", "demo": "migrations\/get-n-host-report.md", @@ -24448,7 +24513,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 228, + "weight": 217, "cookies": false, "type": "", "demo": "migrations\/create-supabase-migration.md", @@ -24503,7 +24568,8 @@ "endpoint": { "type": "string", "description": "Source's Supabase Endpoint", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "apiKey": { "type": "string", @@ -24528,7 +24594,8 @@ "port": { "type": "integer", "description": "Source's Database Port", - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24569,7 +24636,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 236, + "weight": 225, "cookies": false, "type": "", "demo": "migrations\/get-supabase-report.md", @@ -24709,7 +24776,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 233, + "weight": 222, "cookies": false, "type": "", "demo": "migrations\/get.md", @@ -24768,7 +24835,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 238, + "weight": 227, "cookies": false, "type": "", "demo": "migrations\/retry.md", @@ -24820,7 +24887,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 239, + "weight": 228, "cookies": false, "type": "", "demo": "migrations\/delete.md", @@ -24881,7 +24948,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 138, + "weight": 127, "cookies": false, "type": "", "demo": "project\/get-usage.md", @@ -24970,7 +25037,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 140, + "weight": 129, "cookies": false, "type": "", "demo": "project\/list-variables.md", @@ -25017,7 +25084,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 139, + "weight": 128, "cookies": false, "type": "", "demo": "project\/create-variable.md", @@ -25096,7 +25163,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 141, + "weight": 130, "cookies": false, "type": "", "demo": "project\/get-variable.md", @@ -25155,7 +25222,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 142, + "weight": 131, "cookies": false, "type": "", "demo": "project\/update-variable.md", @@ -25238,7 +25305,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 143, + "weight": 132, "cookies": false, "type": "", "demo": "project\/delete-variable.md", @@ -25324,7 +25391,7 @@ "parameters": [ { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search", "required": false, "schema": { "type": "array", @@ -25382,7 +25449,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 92, + "weight": 81, "cookies": false, "type": "", "demo": "projects\/create.md", @@ -25449,7 +25516,8 @@ "url": { "type": "string", "description": "Project URL.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25517,7 +25585,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 93, + "weight": 82, "cookies": false, "type": "", "demo": "projects\/get.md", @@ -25576,7 +25644,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 94, + "weight": 83, "cookies": false, "type": "", "demo": "projects\/update.md", @@ -25635,7 +25703,8 @@ "url": { "type": "string", "description": "Project URL.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25692,7 +25761,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 111, + "weight": 100, "cookies": false, "type": "", "demo": "projects\/delete.md", @@ -25753,7 +25822,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 98, + "weight": 87, "cookies": false, "type": "", "demo": "projects\/update-api-status.md", @@ -25910,7 +25979,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 99, + "weight": 88, "cookies": false, "type": "", "demo": "projects\/update-api-status-all.md", @@ -26050,7 +26119,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 104, + "weight": 93, "cookies": false, "type": "", "demo": "projects\/update-auth-duration.md", @@ -26094,7 +26163,8 @@ "duration": { "type": "integer", "description": "Project session length in seconds. Max length: 31536000 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26130,7 +26200,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 103, + "weight": 92, "cookies": false, "type": "", "demo": "projects\/update-auth-limit.md", @@ -26174,7 +26244,8 @@ "limit": { "type": "integer", "description": "Set the max number of users allowed in this project. Use 0 for unlimited.", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26210,7 +26281,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 109, + "weight": 98, "cookies": false, "type": "", "demo": "projects\/update-auth-sessions-limit.md", @@ -26254,7 +26325,8 @@ "limit": { "type": "integer", "description": "Set the max number of users allowed in this project. Value allowed is between 1-100. Default is 10", - "x-example": 1 + "x-example": 1, + "format": "int32" } }, "required": [ @@ -26290,7 +26362,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 102, + "weight": 91, "cookies": false, "type": "", "demo": "projects\/update-memberships-privacy.md", @@ -26382,7 +26454,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 110, + "weight": 99, "cookies": false, "type": "", "demo": "projects\/update-mock-numbers.md", @@ -26465,7 +26537,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 107, + "weight": 96, "cookies": false, "type": "", "demo": "projects\/update-auth-password-dictionary.md", @@ -26545,7 +26617,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 106, + "weight": 95, "cookies": false, "type": "", "demo": "projects\/update-auth-password-history.md", @@ -26589,7 +26661,8 @@ "limit": { "type": "integer", "description": "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 is20. Default value is 0", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26625,7 +26698,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 108, + "weight": 97, "cookies": false, "type": "", "demo": "projects\/update-personal-data-check.md", @@ -26705,7 +26778,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 101, + "weight": 90, "cookies": false, "type": "", "demo": "projects\/update-session-alerts.md", @@ -26785,7 +26858,7 @@ "x-appwrite": { "method": "updateSessionInvalidation", "group": "auth", - "weight": 137, + "weight": 126, "cookies": false, "type": "", "demo": "projects\/update-session-invalidation.md", @@ -26865,7 +26938,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 105, + "weight": 94, "cookies": false, "type": "", "demo": "projects\/update-auth-status.md", @@ -27346,7 +27419,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 123, + "weight": 112, "cookies": false, "type": "", "demo": "projects\/create-jwt.md", @@ -27457,7 +27530,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -27493,7 +27567,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 119, + "weight": 108, "cookies": false, "type": "", "demo": "projects\/list-keys.md", @@ -27563,7 +27637,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 118, + "weight": 107, "cookies": false, "type": "", "demo": "projects\/create-key.md", @@ -27718,7 +27792,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 120, + "weight": 109, "cookies": false, "type": "", "demo": "projects\/get-key.md", @@ -27787,7 +27861,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 121, + "weight": 110, "cookies": false, "type": "", "demo": "projects\/update-key.md", @@ -27943,7 +28017,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 122, + "weight": 111, "cookies": false, "type": "", "demo": "projects\/delete-key.md", @@ -27990,6 +28064,88 @@ ] } }, + "\/projects\/{projectId}\/labels": { + "put": { + "summary": "Update project labels", + "operationId": "projectsUpdateLabels", + "tags": [ + "projects" + ], + "description": "Update the project labels by its unique ID. Labels can be used to easily filter projects in an organization.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateLabels", + "group": "projects", + "weight": 435, + "cookies": false, + "type": "", + "demo": "projects\/update-labels.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "public": true, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "Array of project labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + } + } + } + } + } + }, "\/projects\/{projectId}\/oauth2": { "patch": { "summary": "Update project OAuth2", @@ -28014,7 +28170,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 100, + "weight": 89, "cookies": false, "type": "", "demo": "projects\/update-o-auth-2.md", @@ -28157,7 +28313,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 125, + "weight": 114, "cookies": false, "type": "", "demo": "projects\/list-platforms.md", @@ -28227,7 +28383,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 124, + "weight": 113, "cookies": false, "type": "", "demo": "projects\/create-platform.md", @@ -28347,7 +28503,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 126, + "weight": 115, "cookies": false, "type": "", "demo": "projects\/get-platform.md", @@ -28416,7 +28572,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 127, + "weight": 116, "cookies": false, "type": "", "demo": "projects\/update-platform.md", @@ -28512,7 +28668,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 128, + "weight": 117, "cookies": false, "type": "", "demo": "projects\/delete-platform.md", @@ -28583,7 +28739,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 96, + "weight": 85, "cookies": false, "type": "", "demo": "projects\/update-service-status.md", @@ -28686,7 +28842,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 97, + "weight": 86, "cookies": false, "type": "", "demo": "projects\/update-service-status-all.md", @@ -28766,7 +28922,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 129, + "weight": 118, "cookies": false, "type": "", "demo": "projects\/update-smtp.md", @@ -28896,12 +29052,14 @@ "senderEmail": { "type": "string", "description": "Email of the sender", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -28911,7 +29069,8 @@ "port": { "type": "integer", "description": "SMTP server port", - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -28961,7 +29120,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 130, + "weight": 119, "cookies": false, "type": "", "demo": "projects\/create-smtp-test.md", @@ -29098,12 +29257,14 @@ "senderEmail": { "type": "string", "description": "Email of the sender", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -29113,7 +29274,8 @@ "port": { "type": "integer", "description": "SMTP server port", - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29173,7 +29335,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 95, + "weight": 84, "cookies": false, "type": "", "demo": "projects\/update-team.md", @@ -29253,7 +29415,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 132, + "weight": 121, "cookies": false, "type": "", "demo": "projects\/get-email-template.md", @@ -29478,7 +29640,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 134, + "weight": 123, "cookies": false, "type": "", "demo": "projects\/update-email-template.md", @@ -29703,12 +29865,14 @@ "senderEmail": { "type": "string", "description": "Email of the sender", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -29743,7 +29907,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 136, + "weight": 125, "cookies": false, "type": "", "demo": "projects\/delete-email-template.md", @@ -29970,7 +30134,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 131, + "weight": 120, "cookies": false, "type": "", "demo": "projects\/get-sms-template.md", @@ -30256,7 +30420,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 133, + "weight": 122, "cookies": false, "type": "", "demo": "projects\/update-sms-template.md", @@ -30565,7 +30729,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 135, + "weight": 124, "cookies": false, "type": "", "demo": "projects\/delete-sms-template.md", @@ -30853,7 +31017,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 113, + "weight": 102, "cookies": false, "type": "", "demo": "projects\/list-webhooks.md", @@ -30923,7 +31087,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 112, + "weight": 101, "cookies": false, "type": "", "demo": "projects\/create-webhook.md", @@ -31039,7 +31203,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 114, + "weight": 103, "cookies": false, "type": "", "demo": "projects\/get-webhook.md", @@ -31108,7 +31272,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 115, + "weight": 104, "cookies": false, "type": "", "demo": "projects\/update-webhook.md", @@ -31225,7 +31389,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 117, + "weight": 106, "cookies": false, "type": "", "demo": "projects\/delete-webhook.md", @@ -31296,7 +31460,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 116, + "weight": 105, "cookies": false, "type": "", "demo": "projects\/update-webhook-signature.md", @@ -31367,7 +31531,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 510, + "weight": 511, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -31452,7 +31616,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 505, + "weight": 506, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -31519,7 +31683,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 507, + "weight": 508, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -31597,7 +31761,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 508, + "weight": 509, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -31633,7 +31797,8 @@ "url": { "type": "string", "description": "Target URL of redirection", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "statusCode": { "type": "string", @@ -31710,7 +31875,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 506, + "weight": 507, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -31788,7 +31953,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 509, + "weight": 510, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -31839,7 +32004,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 511, + "weight": 512, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -31899,7 +32064,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 512, + "weight": 513, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -31959,7 +32124,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 467, + "weight": 468, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -32044,7 +32209,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 465, + "weight": 466, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -32121,7 +32286,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -32297,7 +32463,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 470, + "weight": 471, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -32347,7 +32513,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 493, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -32397,7 +32563,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 489, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -32526,7 +32692,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 490, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -32586,7 +32752,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 491, + "weight": 492, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -32658,7 +32824,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 466, + "weight": 467, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -32718,7 +32884,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 468, + "weight": 469, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -32802,7 +32968,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -32967,7 +33134,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 469, + "weight": 470, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -33029,7 +33196,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 476, + "weight": 477, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -33110,7 +33277,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 475, + "weight": 476, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -33205,7 +33372,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 471, + "weight": 472, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -33268,7 +33435,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -33310,7 +33478,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 479, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -33391,7 +33559,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 472, + "weight": 473, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -33508,7 +33676,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 473, + "weight": 474, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -33607,7 +33775,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 474, + "weight": 475, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -33670,7 +33838,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 477, + "weight": 478, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -33735,7 +33903,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 478, + "weight": 479, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -33826,7 +33994,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 480, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -33898,7 +34066,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 482, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -33984,7 +34152,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 481, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -34047,7 +34215,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -34119,7 +34287,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 492, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -34201,7 +34369,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -34261,7 +34429,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -34353,7 +34521,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -34423,7 +34591,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -34517,7 +34685,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -34589,7 +34757,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 520, + "weight": 521, "cookies": false, "type": "", "demo": "storage\/list-buckets.md", @@ -34675,7 +34843,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 518, + "weight": 519, "cookies": false, "type": "", "demo": "storage\/create-bucket.md", @@ -34738,7 +34906,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -34750,7 +34919,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "x-example": "none", "enum": [ "none", @@ -34810,7 +34979,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 519, + "weight": 520, "cookies": false, "type": "", "demo": "storage\/get-bucket.md", @@ -34871,7 +35040,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 521, + "weight": 522, "cookies": false, "type": "", "demo": "storage\/update-bucket.md", @@ -34941,7 +35110,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -34953,7 +35123,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "x-example": "none", "enum": [ "none", @@ -35003,7 +35173,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 522, + "weight": 523, "cookies": false, "type": "", "demo": "storage\/delete-bucket.md", @@ -35066,7 +35236,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 525, + "weight": 526, "cookies": false, "type": "", "demo": "storage\/list-files.md", @@ -35165,7 +35335,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 523, + "weight": 524, "cookies": false, "type": "upload", "demo": "storage\/create-file.md", @@ -35220,7 +35390,8 @@ "file": { "type": "string", "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", - "x-example": null + "x-example": null, + "format": "binary" }, "permissions": { "type": "array", @@ -35266,7 +35437,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 524, + "weight": 525, "cookies": false, "type": "", "demo": "storage\/get-file.md", @@ -35340,7 +35511,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 526, + "weight": 527, "cookies": false, "type": "", "demo": "storage\/update-file.md", @@ -35432,7 +35603,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 527, + "weight": 528, "cookies": false, "type": "", "demo": "storage\/delete-file.md", @@ -35501,7 +35672,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 529, + "weight": 530, "cookies": false, "type": "location", "demo": "storage\/get-file-download.md", @@ -35581,7 +35752,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 528, + "weight": 529, "cookies": false, "type": "location", "demo": "storage\/get-file-preview.md", @@ -35811,7 +35982,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 530, + "weight": 531, "cookies": false, "type": "location", "demo": "storage\/get-file-view.md", @@ -35898,7 +36069,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 532, + "weight": 533, "cookies": false, "type": "", "demo": "storage\/get-usage.md", @@ -35971,7 +36142,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 533, + "weight": 534, "cookies": false, "type": "", "demo": "storage\/get-bucket-usage.md", @@ -36331,7 +36502,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -38078,6 +38250,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -38194,6 +38367,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -38554,18 +38728,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -38682,18 +38859,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -38807,18 +38987,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -38935,18 +39118,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -40132,7 +40318,8 @@ "size": { "type": "integer", "description": "Column size for text columns, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -40271,6 +40458,7 @@ "type": "integer", "description": "Maximum size of the string column.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -40384,6 +40572,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -40500,6 +40689,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -42621,12 +42811,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -42747,12 +42939,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -43000,7 +43194,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -43089,7 +43283,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -43176,7 +43370,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -43240,7 +43434,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -43316,7 +43510,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -43382,7 +43576,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 157, + "weight": 146, "cookies": false, "type": "", "demo": "teams\/list-logs.md", @@ -43467,7 +43661,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -43566,7 +43760,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -43615,7 +43809,8 @@ "email": { "type": "string", "description": "Email of the new team member.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -43625,7 +43820,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -43645,7 +43841,8 @@ "url": { "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -43686,7 +43883,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -43760,7 +43957,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -43856,7 +44053,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -43932,7 +44129,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -44031,7 +44228,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -44093,7 +44290,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -44176,7 +44373,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 515, + "weight": 516, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -44270,7 +44467,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 513, + "weight": 514, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -44359,7 +44556,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 514, + "weight": 515, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -44419,7 +44616,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 516, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -44489,7 +44686,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 517, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -44551,7 +44748,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -44637,7 +44834,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -44677,12 +44874,14 @@ "type": "string", "description": "User email.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -44729,7 +44928,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -44768,12 +44967,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44816,7 +45017,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -44855,12 +45056,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44903,7 +45106,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -44984,7 +45187,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -45047,7 +45250,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -45086,12 +45289,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45134,7 +45339,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -45173,12 +45378,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45221,7 +45428,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -45260,12 +45467,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45275,22 +45484,26 @@ "passwordCpu": { "type": "integer", "description": "Optional CPU cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -45338,7 +45551,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -45377,12 +45590,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45443,7 +45658,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -45482,12 +45697,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -45550,7 +45767,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 189, "cookies": false, "type": "", "demo": "users\/get-usage.md", @@ -45623,7 +45840,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -45677,7 +45894,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -45740,7 +45957,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -45786,7 +46003,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -45822,7 +46040,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -45873,7 +46091,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -45906,7 +46125,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -45991,7 +46210,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -46078,7 +46297,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -46176,7 +46395,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -46311,7 +46530,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -46447,7 +46666,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -46566,7 +46785,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -46683,7 +46902,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -46800,7 +47019,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -46919,7 +47138,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -47001,7 +47220,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -47083,7 +47302,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -47129,7 +47348,8 @@ "number": { "type": "string", "description": "User phone number.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -47165,7 +47385,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -47226,7 +47446,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -47308,7 +47528,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -47380,7 +47600,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -47434,7 +47654,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -47490,7 +47710,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -47563,7 +47783,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -47645,7 +47865,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -47730,7 +47950,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -47841,7 +48061,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -47912,7 +48132,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -48002,7 +48222,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -48075,7 +48295,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -48121,12 +48341,14 @@ "length": { "type": "integer", "description": "Token length in characters. The default length is 6 characters", - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -48159,7 +48381,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -48241,7 +48463,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -48323,7 +48545,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 204, + "weight": 193, "cookies": false, "type": "", "demo": "vcs\/create-repository-detection.md", @@ -48420,7 +48642,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 205, + "weight": 194, "cookies": false, "type": "", "demo": "vcs\/list-repositories.md", @@ -48519,7 +48741,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 206, + "weight": 195, "cookies": false, "type": "", "demo": "vcs\/create-repository.md", @@ -48605,7 +48827,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 207, + "weight": 196, "cookies": false, "type": "", "demo": "vcs\/get-repository.md", @@ -48676,7 +48898,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 208, + "weight": 197, "cookies": false, "type": "", "demo": "vcs\/list-repository-branches.md", @@ -48747,7 +48969,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 203, + "weight": 192, "cookies": false, "type": "", "demo": "vcs\/get-repository-contents.md", @@ -48833,7 +49055,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 213, + "weight": 202, "cookies": false, "type": "", "demo": "vcs\/update-external-deployments.md", @@ -48923,7 +49145,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 210, + "weight": 199, "cookies": false, "type": "", "demo": "vcs\/list-installations.md", @@ -49009,7 +49231,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 211, + "weight": 200, "cookies": false, "type": "", "demo": "vcs\/get-installation.md", @@ -49061,7 +49283,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 212, + "weight": 201, "cookies": false, "type": "", "demo": "vcs\/delete-installation.md", @@ -51029,14 +51251,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { @@ -52478,14 +52700,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { @@ -55069,7 +55291,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "description": "Compression algorithm chosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", "x-example": "gzip" }, "encryption": { @@ -55086,6 +55308,12 @@ "type": "boolean", "description": "Image transformations are enabled.", "x-example": false + }, + "totalSize": { + "type": "integer", + "description": "Total size of this bucket in bytes.", + "x-example": 128, + "format": "int32" } }, "required": [ @@ -55101,7 +55329,8 @@ "compression", "encryption", "antivirus", - "transformations" + "transformations", + "totalSize" ], "example": { "$id": "5e5ea5c16897e", @@ -55121,7 +55350,8 @@ "compression": "gzip", "encryption": false, "antivirus": false, - "transformations": false + "transformations": false, + "totalSize": 128 } }, "resourceToken": { @@ -57488,6 +57718,16 @@ "description": "Last ping datetime in ISO 8601 format.", "x-example": "2020-10-15T06:38:00.000+00:00" }, + "labels": { + "type": "array", + "description": "Labels for the project.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, "authEmailPassword": { "type": "boolean", "description": "Email\/Password auth method status", @@ -57632,6 +57872,7 @@ "smtpSecure", "pingCount", "pingedAt", + "labels", "authEmailPassword", "authUsersAuthMagicURL", "authEmailOtp", @@ -57700,6 +57941,9 @@ "smtpSecure": "tls", "pingCount": 1, "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [ + "vip" + ], "authEmailPassword": true, "authUsersAuthMagicURL": true, "authEmailOtp": true, @@ -59653,160 +59897,6 @@ "description": "Time range of the usage stats.", "x-example": "30d" }, - "deploymentsTotal": { - "type": "integer", - "description": "Total aggregated number of functions deployments.", - "x-example": 0, - "format": "int32" - }, - "deploymentsStorageTotal": { - "type": "integer", - "description": "Total aggregated sum of functions deployment storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTotal": { - "type": "integer", - "description": "Total aggregated number of functions build.", - "x-example": 0, - "format": "int32" - }, - "buildsStorageTotal": { - "type": "integer", - "description": "total aggregated sum of functions build storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTimeTotal": { - "type": "integer", - "description": "Total aggregated sum of functions build compute time.", - "x-example": 0, - "format": "int32" - }, - "buildsMbSecondsTotal": { - "type": "integer", - "description": "Total aggregated sum of functions build mbSeconds.", - "x-example": 0, - "format": "int32" - }, - "executionsTotal": { - "type": "integer", - "description": "Total aggregated number of functions execution.", - "x-example": 0, - "format": "int32" - }, - "executionsTimeTotal": { - "type": "integer", - "description": "Total aggregated sum of functions execution compute time.", - "x-example": 0, - "format": "int32" - }, - "executionsMbSecondsTotal": { - "type": "integer", - "description": "Total aggregated sum of functions execution mbSeconds.", - "x-example": 0, - "format": "int32" - }, - "deployments": { - "type": "array", - "description": "Aggregated number of functions deployment per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "deploymentsStorage": { - "type": "array", - "description": "Aggregated number of functions deployment storage per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsSuccessTotal": { - "type": "integer", - "description": "Total aggregated number of successful function builds.", - "x-example": 0, - "format": "int32" - }, - "buildsFailedTotal": { - "type": "integer", - "description": "Total aggregated number of failed function builds.", - "x-example": 0, - "format": "int32" - }, - "builds": { - "type": "array", - "description": "Aggregated number of functions build per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsStorage": { - "type": "array", - "description": "Aggregated sum of functions build storage per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsTime": { - "type": "array", - "description": "Aggregated sum of functions build compute time per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsMbSeconds": { - "type": "array", - "description": "Aggregated sum of functions build mbSeconds per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "executions": { - "type": "array", - "description": "Aggregated number of functions execution per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "executionsTime": { - "type": "array", - "description": "Aggregated number of functions execution compute time per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "executionsMbSeconds": { - "type": "array", - "description": "Aggregated number of functions mbSeconds per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsSuccess": { - "type": "array", - "description": "Aggregated number of successful function builds per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, - "buildsFailed": { - "type": "array", - "description": "Aggregated number of failed function builds per period.", - "items": { - "$ref": "#\/components\/schemas\/metric" - }, - "x-example": [] - }, "sitesTotal": { "type": "integer", "description": "Total aggregated number of sites.", @@ -59821,6 +59911,60 @@ }, "x-example": [] }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of sites deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of sites deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of sites build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of sites build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of sites execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of sites execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of sites execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, "requestsTotal": { "type": "integer", "description": "Total aggregated number of requests.", @@ -59862,10 +60006,112 @@ "$ref": "#\/components\/schemas\/metric" }, "x-example": [] + }, + "deployments": { + "type": "array", + "description": "Aggregated number of sites deployment per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of sites deployment storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful site builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed site builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of sites build per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of sites build storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of sites build compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of sites build mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of sites execution per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of sites execution compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of sites mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful site builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed site builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] } }, "required": [ "range", + "sitesTotal", + "sites", "deploymentsTotal", "deploymentsStorageTotal", "buildsTotal", @@ -59875,6 +60121,12 @@ "executionsTotal", "executionsTimeTotal", "executionsMbSecondsTotal", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound", "deployments", "deploymentsStorage", "buildsSuccessTotal", @@ -59887,18 +60139,12 @@ "executionsTime", "executionsMbSeconds", "buildsSuccess", - "buildsFailed", - "sitesTotal", - "sites", - "requestsTotal", - "requests", - "inboundTotal", - "inbound", - "outboundTotal", - "outbound" + "buildsFailed" ], "example": { "range": "30d", + "sitesTotal": 0, + "sites": [], "deploymentsTotal": 0, "deploymentsStorageTotal": 0, "buildsTotal": 0, @@ -59908,6 +60154,12 @@ "executionsTotal": 0, "executionsTimeTotal": 0, "executionsMbSecondsTotal": 0, + "requestsTotal": 0, + "requests": [], + "inboundTotal": 0, + "inbound": [], + "outboundTotal": 0, + "outbound": [], "deployments": [], "deploymentsStorage": [], "buildsSuccessTotal": 0, @@ -59920,15 +60172,7 @@ "executionsTime": [], "executionsMbSeconds": [], "buildsSuccess": [], - "buildsFailed": [], - "sitesTotal": 0, - "sites": [], - "requestsTotal": 0, - "requests": [], - "inboundTotal": 0, - "inbound": [], - "outboundTotal": 0, - "outbound": [] + "buildsFailed": [] } }, "usageSite": { diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json index 2a0081b378..e82f3e5b78 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.8.0", + "version": "1.8.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -142,7 +142,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -227,12 +228,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -445,7 +448,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -558,7 +562,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -631,7 +635,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -758,7 +762,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -901,7 +905,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1028,7 +1032,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1165,7 +1169,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1306,7 +1310,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1410,7 +1414,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1512,7 +1516,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1614,7 +1618,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1833,7 +1837,8 @@ "oldPassword": { "type": "string", "description": "Current user password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1906,12 +1911,14 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2113,12 +2120,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2428,12 +2437,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3001,7 +3012,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3088,12 +3100,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3321,7 +3335,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3449,7 +3464,8 @@ "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -3747,7 +3763,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -3877,7 +3893,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4013,7 +4029,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4075,7 +4091,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4567,7 +4583,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4653,7 +4669,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -4749,7 +4765,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -4845,7 +4861,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -5948,7 +5964,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7721,6 +7738,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -7839,6 +7857,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8205,18 +8224,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8335,18 +8357,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -8462,18 +8487,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -8592,18 +8620,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -9809,7 +9840,8 @@ "size": { "type": "integer", "description": "Attribute size for text attributes, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -9950,6 +9982,7 @@ "type": "integer", "description": "Maximum size of the string attribute.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10065,6 +10098,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10183,6 +10217,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -11774,12 +11809,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -11903,12 +11940,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12355,7 +12394,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -12441,7 +12480,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 435, + "weight": 436, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -12582,7 +12621,8 @@ "timeout": { "type": "integer", "description": "Function maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -12737,7 +12777,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -12788,7 +12828,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 441, + "weight": 442, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -12839,7 +12879,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -12900,7 +12940,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -13048,7 +13088,8 @@ "timeout": { "type": "integer", "description": "Maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13193,7 +13234,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -13256,7 +13297,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 444, + "weight": 445, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -13338,7 +13379,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 445, + "weight": 446, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -13434,7 +13475,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 442, + "weight": 443, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -13492,7 +13533,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -13534,7 +13576,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 450, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -13621,7 +13663,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 447, + "weight": 448, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -13739,7 +13781,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 448, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -13838,7 +13880,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 443, + "weight": 444, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -13902,7 +13944,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 446, + "weight": 447, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -13968,7 +14010,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 449, + "weight": 450, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -14060,7 +14102,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 451, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -14133,7 +14175,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 454, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -14222,7 +14264,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 452, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -14342,7 +14384,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 453, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -14410,7 +14452,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 455, + "weight": 456, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -14483,7 +14525,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 460, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -14544,7 +14586,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 458, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -14637,7 +14679,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 459, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -14708,7 +14750,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 461, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -14803,7 +14845,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 462, + "weight": 463, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -14876,7 +14918,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -14932,7 +14974,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -14988,7 +15030,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -15040,7 +15082,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -15092,7 +15134,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -15144,7 +15186,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -15207,7 +15249,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -15259,7 +15301,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -15311,7 +15353,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -15376,7 +15418,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -15441,7 +15483,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -15517,7 +15559,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -15582,7 +15624,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -15627,6 +15669,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -15673,7 +15716,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -15738,7 +15781,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -15803,7 +15846,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -15868,7 +15911,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -15933,7 +15976,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -15998,7 +16041,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -16063,7 +16106,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -16128,7 +16171,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -16193,7 +16236,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -16245,7 +16288,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -16297,7 +16340,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -16349,7 +16392,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -16405,7 +16448,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -16461,7 +16504,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -16517,7 +16560,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -16573,7 +16616,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -16629,7 +16672,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -16685,7 +16728,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -16741,7 +16784,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -16797,7 +16840,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -16886,7 +16929,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -17033,7 +17076,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -17192,7 +17235,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -17302,7 +17345,8 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -17370,7 +17414,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -17499,6 +17543,7 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS platforms.", "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -17568,7 +17613,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -17752,7 +17797,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -17942,7 +17987,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -17997,7 +18042,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -18061,7 +18106,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -18149,7 +18194,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -18237,7 +18282,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -18326,7 +18371,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -18508,7 +18553,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -18692,7 +18737,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -18847,7 +18892,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -19003,7 +19048,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -19069,7 +19114,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19079,7 +19125,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19122,7 +19169,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -19201,7 +19248,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19244,7 +19292,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -19342,7 +19390,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -19443,7 +19491,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -19498,7 +19546,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19508,7 +19557,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19551,7 +19601,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -19619,7 +19669,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19662,7 +19713,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -19717,7 +19768,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19727,7 +19779,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19770,7 +19823,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -19838,7 +19891,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19881,7 +19935,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -20019,7 +20073,8 @@ "port": { "type": "integer", "description": "The default SMTP server port.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -20061,7 +20116,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20071,7 +20127,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20115,7 +20172,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -20257,6 +20314,7 @@ "type": "integer", "description": "SMTP port.", "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -20300,7 +20358,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20349,7 +20408,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -20394,7 +20453,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -20447,7 +20507,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -20548,7 +20608,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -20593,7 +20653,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -20646,7 +20707,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -20747,7 +20808,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -20792,7 +20853,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -20845,7 +20907,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -20946,7 +21008,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -20991,7 +21053,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -21044,7 +21107,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -21145,7 +21208,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -21200,7 +21263,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -21264,7 +21327,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -21352,7 +21415,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -21440,7 +21503,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -21527,7 +21590,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -21612,7 +21675,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -21674,7 +21737,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -21755,7 +21818,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -21819,7 +21882,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -21907,7 +21970,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -22004,7 +22067,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -22097,7 +22160,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -22162,7 +22225,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -22240,7 +22303,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 467, + "weight": 468, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -22326,7 +22389,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 465, + "weight": 466, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -22404,7 +22467,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -22580,7 +22644,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 470, + "weight": 471, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -22631,7 +22695,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 493, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -22682,7 +22746,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 466, + "weight": 467, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -22743,7 +22807,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 468, + "weight": 469, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -22828,7 +22892,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -22993,7 +23058,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 469, + "weight": 470, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -23056,7 +23121,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 476, + "weight": 477, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -23138,7 +23203,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 475, + "weight": 476, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -23234,7 +23299,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 471, + "weight": 472, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -23298,7 +23363,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -23340,7 +23406,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 479, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -23422,7 +23488,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 472, + "weight": 473, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -23540,7 +23606,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 473, + "weight": 474, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -23640,7 +23706,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 474, + "weight": 475, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -23704,7 +23770,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 477, + "weight": 478, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -23770,7 +23836,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 478, + "weight": 479, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -23862,7 +23928,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 480, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -23935,7 +24001,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 482, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -24022,7 +24088,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 481, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -24086,7 +24152,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -24159,7 +24225,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -24220,7 +24286,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -24313,7 +24379,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -24384,7 +24450,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -24479,7 +24545,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -24552,7 +24618,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 520, + "weight": 521, "cookies": false, "type": "", "demo": "storage\/list-buckets.md", @@ -24639,7 +24705,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 518, + "weight": 519, "cookies": false, "type": "", "demo": "storage\/create-bucket.md", @@ -24703,7 +24769,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -24715,7 +24782,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "x-example": "none", "enum": [ "none", @@ -24775,7 +24842,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 519, + "weight": 520, "cookies": false, "type": "", "demo": "storage\/get-bucket.md", @@ -24837,7 +24904,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 521, + "weight": 522, "cookies": false, "type": "", "demo": "storage\/update-bucket.md", @@ -24908,7 +24975,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -24920,7 +24988,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "x-example": "none", "enum": [ "none", @@ -24970,7 +25038,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 522, + "weight": 523, "cookies": false, "type": "", "demo": "storage\/delete-bucket.md", @@ -25034,7 +25102,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 525, + "weight": 526, "cookies": false, "type": "", "demo": "storage\/list-files.md", @@ -25135,7 +25203,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 523, + "weight": 524, "cookies": false, "type": "upload", "demo": "storage\/create-file.md", @@ -25192,7 +25260,8 @@ "file": { "type": "string", "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", - "x-example": null + "x-example": null, + "format": "binary" }, "permissions": { "type": "array", @@ -25238,7 +25307,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 524, + "weight": 525, "cookies": false, "type": "", "demo": "storage\/get-file.md", @@ -25314,7 +25383,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 526, + "weight": 527, "cookies": false, "type": "", "demo": "storage\/update-file.md", @@ -25408,7 +25477,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 527, + "weight": 528, "cookies": false, "type": "", "demo": "storage\/delete-file.md", @@ -25479,7 +25548,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 529, + "weight": 530, "cookies": false, "type": "location", "demo": "storage\/get-file-download.md", @@ -25561,7 +25630,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 528, + "weight": 529, "cookies": false, "type": "location", "demo": "storage\/get-file-preview.md", @@ -25793,7 +25862,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 530, + "weight": 531, "cookies": false, "type": "location", "demo": "storage\/get-file-view.md", @@ -26165,7 +26234,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -27835,6 +27905,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -27952,6 +28023,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -28315,18 +28387,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -28444,18 +28519,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -28570,18 +28648,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -28699,18 +28780,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -29906,7 +29990,8 @@ "size": { "type": "integer", "description": "Column size for text columns, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -30046,6 +30131,7 @@ "type": "integer", "description": "Maximum size of the string column.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -30160,6 +30246,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -30277,6 +30364,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -32242,12 +32330,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32370,12 +32460,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32415,7 +32507,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -32506,7 +32598,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -32595,7 +32687,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -32661,7 +32753,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -32739,7 +32831,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -32807,7 +32899,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -32908,7 +33000,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -32959,7 +33051,8 @@ "email": { "type": "string", "description": "Email of the new team member.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -32969,7 +33062,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -32989,7 +33083,8 @@ "url": { "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -33030,7 +33125,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -33106,7 +33201,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -33204,7 +33299,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -33282,7 +33377,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -33383,7 +33478,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -33447,7 +33542,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -33532,7 +33627,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 515, + "weight": 516, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -33627,7 +33722,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 513, + "weight": 514, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -33717,7 +33812,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 514, + "weight": 515, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -33778,7 +33873,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 516, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -33849,7 +33944,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 517, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -33912,7 +34007,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -33999,7 +34094,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -34040,12 +34135,14 @@ "type": "string", "description": "User email.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -34092,7 +34189,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -34132,12 +34229,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34180,7 +34279,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -34220,12 +34319,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34268,7 +34369,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -34350,7 +34451,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -34414,7 +34515,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -34454,12 +34555,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34502,7 +34605,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -34542,12 +34645,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34590,7 +34695,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -34630,12 +34735,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34645,22 +34752,26 @@ "passwordCpu": { "type": "integer", "description": "Optional CPU cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -34708,7 +34819,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -34748,12 +34859,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34814,7 +34927,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -34854,12 +34967,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -34922,7 +35037,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -34977,7 +35092,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -35041,7 +35156,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -35088,7 +35203,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -35124,7 +35240,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -35176,7 +35292,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -35209,7 +35326,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -35295,7 +35412,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -35383,7 +35500,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -35482,7 +35599,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -35620,7 +35737,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -35759,7 +35876,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -35881,7 +35998,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -36001,7 +36118,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -36121,7 +36238,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -36243,7 +36360,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -36326,7 +36443,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -36409,7 +36526,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -36456,7 +36573,8 @@ "number": { "type": "string", "description": "User phone number.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -36492,7 +36610,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -36554,7 +36672,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -36637,7 +36755,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -36710,7 +36828,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -36765,7 +36883,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -36822,7 +36940,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -36896,7 +37014,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -36979,7 +37097,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -37065,7 +37183,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -37177,7 +37295,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -37249,7 +37367,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -37340,7 +37458,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -37414,7 +37532,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -37461,12 +37579,14 @@ "length": { "type": "integer", "description": "Token length in characters. The default length is 6 characters", - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -37499,7 +37619,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -37582,7 +37702,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -39180,14 +39300,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { @@ -40629,14 +40749,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { @@ -43220,7 +43340,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "description": "Compression algorithm chosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", "x-example": "gzip" }, "encryption": { @@ -43237,6 +43357,12 @@ "type": "boolean", "description": "Image transformations are enabled.", "x-example": false + }, + "totalSize": { + "type": "integer", + "description": "Total size of this bucket in bytes.", + "x-example": 128, + "format": "int32" } }, "required": [ @@ -43252,7 +43378,8 @@ "compression", "encryption", "antivirus", - "transformations" + "transformations", + "totalSize" ], "example": { "$id": "5e5ea5c16897e", @@ -43272,7 +43399,8 @@ "compression": "gzip", "encryption": false, "antivirus": false, - "transformations": false + "transformations": false, + "totalSize": 128 } }, "resourceToken": { diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index fd35c3b73c..4bb90a535f 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -140,7 +140,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -224,12 +225,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -439,7 +442,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -551,7 +555,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -623,7 +627,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -747,7 +751,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -887,7 +891,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1011,7 +1015,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1145,7 +1149,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1283,7 +1287,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1384,7 +1388,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1483,7 +1487,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1582,7 +1586,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1796,7 +1800,8 @@ "oldPassword": { "type": "string", "description": "Current user password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1868,12 +1873,14 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2072,12 +2079,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2382,12 +2391,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3304,7 +3315,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3390,12 +3402,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3621,7 +3635,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3746,7 +3761,8 @@ "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4039,7 +4055,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4167,7 +4183,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4301,7 +4317,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4361,7 +4377,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4851,7 +4867,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4935,7 +4951,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5029,7 +5045,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5123,7 +5139,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -5980,7 +5996,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7146,12 +7163,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7273,12 +7292,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7598,7 +7619,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -7652,7 +7673,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -7706,7 +7727,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -7760,7 +7781,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -7814,7 +7835,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -7868,7 +7889,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -7922,7 +7943,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -7976,7 +7997,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -8030,7 +8051,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -8084,7 +8105,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -8138,7 +8159,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -8222,7 +8243,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -8452,7 +8473,8 @@ "file": { "type": "string", "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", - "x-example": null + "x-example": null, + "format": "binary" }, "permissions": { "type": "array", @@ -9240,7 +9262,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -10403,12 +10426,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10529,12 +10554,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10574,7 +10601,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -10663,7 +10690,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -10750,7 +10777,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -10814,7 +10841,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -10890,7 +10917,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -10956,7 +10983,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -11055,7 +11082,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -11104,7 +11131,8 @@ "email": { "type": "string", "description": "Email of the new team member.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -11114,7 +11142,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -11134,7 +11163,8 @@ "url": { "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -11175,7 +11205,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -11249,7 +11279,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -11345,7 +11375,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -11421,7 +11451,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -11521,7 +11551,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -11584,7 +11614,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 952f83af6d..22f247843f 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -138,7 +138,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -261,12 +262,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -473,7 +476,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -584,7 +588,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -655,7 +659,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -778,7 +782,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -917,7 +921,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1040,7 +1044,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1173,7 +1177,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1310,7 +1314,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1410,7 +1414,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1508,7 +1512,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1606,7 +1610,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1817,7 +1821,8 @@ "oldPassword": { "type": "string", "description": "Current user password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1888,12 +1893,14 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2089,12 +2096,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2394,12 +2403,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3304,7 +3315,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3389,12 +3401,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3618,7 +3632,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3742,7 +3757,8 @@ "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4032,7 +4048,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4160,7 +4176,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4294,7 +4310,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4354,7 +4370,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4844,7 +4860,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4928,7 +4944,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5022,7 +5038,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5116,7 +5132,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -6387,7 +6403,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -8239,6 +8256,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -8356,6 +8374,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8719,18 +8738,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8848,18 +8870,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -8974,18 +8999,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -9103,18 +9131,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -10310,7 +10341,8 @@ "size": { "type": "integer", "description": "Attribute size for text attributes, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -10450,6 +10482,7 @@ "type": "integer", "description": "Maximum size of the string attribute.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10564,6 +10597,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10681,6 +10715,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -12346,12 +12381,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12473,12 +12510,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -13556,7 +13595,8 @@ "timeout": { "type": "integer", "description": "Function maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -14342,7 +14382,8 @@ "timeout": { "type": "integer", "description": "Maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -14782,7 +14823,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -16229,7 +16271,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -16283,7 +16325,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -16337,7 +16379,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -16388,7 +16430,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -16439,7 +16481,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -16490,7 +16532,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -16552,7 +16594,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -16603,7 +16645,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -16654,7 +16696,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -16718,7 +16760,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -16782,7 +16824,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -16857,7 +16899,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -16921,7 +16963,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -16965,6 +17007,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -17011,7 +17054,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -17075,7 +17118,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -17139,7 +17182,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -17203,7 +17246,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -17267,7 +17310,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -17331,7 +17374,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -17395,7 +17438,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -17459,7 +17502,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -17523,7 +17566,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -17574,7 +17617,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -17625,7 +17668,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -17676,7 +17719,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -17730,7 +17773,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -17784,7 +17827,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -17838,7 +17881,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -17892,7 +17935,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -17946,7 +17989,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -18000,7 +18043,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -18054,7 +18097,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -18108,7 +18151,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -18196,7 +18239,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -18342,7 +18385,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -18500,7 +18543,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -18609,7 +18652,8 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -18677,7 +18721,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -18805,6 +18849,7 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS platforms.", "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -18874,7 +18919,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -19055,7 +19100,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -19242,7 +19287,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -19296,7 +19341,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -19359,7 +19404,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -19446,7 +19491,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -19533,7 +19578,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -19621,7 +19666,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -19800,7 +19845,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -19981,7 +20026,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -20133,7 +20178,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -20286,7 +20331,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -20351,7 +20396,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20361,7 +20407,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20404,7 +20451,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -20482,7 +20529,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20525,7 +20573,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -20622,7 +20670,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -20722,7 +20770,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -20776,7 +20824,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20786,7 +20835,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20829,7 +20879,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -20896,7 +20946,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20939,7 +20990,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -20993,7 +21044,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21003,7 +21055,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21046,7 +21099,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -21113,7 +21166,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21156,7 +21210,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -21291,7 +21345,8 @@ "port": { "type": "integer", "description": "The default SMTP server port.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -21333,7 +21388,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21343,7 +21399,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21387,7 +21444,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -21526,6 +21583,7 @@ "type": "integer", "description": "SMTP port.", "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -21569,7 +21627,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21618,7 +21677,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -21662,7 +21721,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -21715,7 +21775,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -21815,7 +21875,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -21859,7 +21919,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -21912,7 +21973,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -22012,7 +22073,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -22056,7 +22117,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -22109,7 +22171,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -22209,7 +22271,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -22253,7 +22315,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -22306,7 +22369,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -22406,7 +22469,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -22460,7 +22523,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -22523,7 +22586,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -22610,7 +22673,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -22697,7 +22760,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -22783,7 +22846,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -22867,7 +22930,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -22928,7 +22991,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -23008,7 +23071,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -23071,7 +23134,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -23158,7 +23221,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -23254,7 +23317,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -23345,7 +23408,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -23409,7 +23472,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -23485,7 +23548,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 232, + "weight": 221, "cookies": false, "type": "", "demo": "migrations\/list.md", @@ -23571,7 +23634,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 226, + "weight": 215, "cookies": false, "type": "", "demo": "migrations\/create-appwrite-migration.md", @@ -23631,7 +23694,8 @@ "endpoint": { "type": "string", "description": "Source Appwrite endpoint", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "projectId": { "type": "string", @@ -23680,7 +23744,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 234, + "weight": 223, "cookies": false, "type": "", "demo": "migrations\/get-appwrite-report.md", @@ -23794,7 +23858,7 @@ "x-appwrite": { "method": "createCSVExport", "group": null, - "weight": 231, + "weight": 220, "cookies": false, "type": "", "demo": "migrations\/create-csv-export.md", @@ -23909,7 +23973,7 @@ "x-appwrite": { "method": "createCSVImport", "group": null, - "weight": 230, + "weight": 219, "cookies": false, "type": "", "demo": "migrations\/create-csv-import.md", @@ -23994,7 +24058,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 227, + "weight": 216, "cookies": false, "type": "", "demo": "migrations\/create-firebase-migration.md", @@ -24085,7 +24149,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 235, + "weight": 224, "cookies": false, "type": "", "demo": "migrations\/get-firebase-report.md", @@ -24172,7 +24236,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 229, + "weight": 218, "cookies": false, "type": "", "demo": "migrations\/create-n-host-migration.md", @@ -24257,7 +24321,8 @@ "port": { "type": "integer", "description": "Source's Database Port", - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24299,7 +24364,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 237, + "weight": 226, "cookies": false, "type": "", "demo": "migrations\/get-n-host-report.md", @@ -24448,7 +24513,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 228, + "weight": 217, "cookies": false, "type": "", "demo": "migrations\/create-supabase-migration.md", @@ -24503,7 +24568,8 @@ "endpoint": { "type": "string", "description": "Source's Supabase Endpoint", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "apiKey": { "type": "string", @@ -24528,7 +24594,8 @@ "port": { "type": "integer", "description": "Source's Database Port", - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24569,7 +24636,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 236, + "weight": 225, "cookies": false, "type": "", "demo": "migrations\/get-supabase-report.md", @@ -24709,7 +24776,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 233, + "weight": 222, "cookies": false, "type": "", "demo": "migrations\/get.md", @@ -24768,7 +24835,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 238, + "weight": 227, "cookies": false, "type": "", "demo": "migrations\/retry.md", @@ -24820,7 +24887,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 239, + "weight": 228, "cookies": false, "type": "", "demo": "migrations\/delete.md", @@ -24881,7 +24948,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 138, + "weight": 127, "cookies": false, "type": "", "demo": "project\/get-usage.md", @@ -24970,7 +25037,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 140, + "weight": 129, "cookies": false, "type": "", "demo": "project\/list-variables.md", @@ -25017,7 +25084,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 139, + "weight": 128, "cookies": false, "type": "", "demo": "project\/create-variable.md", @@ -25096,7 +25163,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 141, + "weight": 130, "cookies": false, "type": "", "demo": "project\/get-variable.md", @@ -25155,7 +25222,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 142, + "weight": 131, "cookies": false, "type": "", "demo": "project\/update-variable.md", @@ -25238,7 +25305,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 143, + "weight": 132, "cookies": false, "type": "", "demo": "project\/delete-variable.md", @@ -25324,7 +25391,7 @@ "parameters": [ { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search", "required": false, "schema": { "type": "array", @@ -25382,7 +25449,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 92, + "weight": 81, "cookies": false, "type": "", "demo": "projects\/create.md", @@ -25449,7 +25516,8 @@ "url": { "type": "string", "description": "Project URL.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25517,7 +25585,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 93, + "weight": 82, "cookies": false, "type": "", "demo": "projects\/get.md", @@ -25576,7 +25644,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 94, + "weight": 83, "cookies": false, "type": "", "demo": "projects\/update.md", @@ -25635,7 +25703,8 @@ "url": { "type": "string", "description": "Project URL.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25692,7 +25761,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 111, + "weight": 100, "cookies": false, "type": "", "demo": "projects\/delete.md", @@ -25753,7 +25822,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 98, + "weight": 87, "cookies": false, "type": "", "demo": "projects\/update-api-status.md", @@ -25910,7 +25979,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 99, + "weight": 88, "cookies": false, "type": "", "demo": "projects\/update-api-status-all.md", @@ -26050,7 +26119,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 104, + "weight": 93, "cookies": false, "type": "", "demo": "projects\/update-auth-duration.md", @@ -26094,7 +26163,8 @@ "duration": { "type": "integer", "description": "Project session length in seconds. Max length: 31536000 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26130,7 +26200,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 103, + "weight": 92, "cookies": false, "type": "", "demo": "projects\/update-auth-limit.md", @@ -26174,7 +26244,8 @@ "limit": { "type": "integer", "description": "Set the max number of users allowed in this project. Use 0 for unlimited.", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26210,7 +26281,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 109, + "weight": 98, "cookies": false, "type": "", "demo": "projects\/update-auth-sessions-limit.md", @@ -26254,7 +26325,8 @@ "limit": { "type": "integer", "description": "Set the max number of users allowed in this project. Value allowed is between 1-100. Default is 10", - "x-example": 1 + "x-example": 1, + "format": "int32" } }, "required": [ @@ -26290,7 +26362,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 102, + "weight": 91, "cookies": false, "type": "", "demo": "projects\/update-memberships-privacy.md", @@ -26382,7 +26454,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 110, + "weight": 99, "cookies": false, "type": "", "demo": "projects\/update-mock-numbers.md", @@ -26465,7 +26537,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 107, + "weight": 96, "cookies": false, "type": "", "demo": "projects\/update-auth-password-dictionary.md", @@ -26545,7 +26617,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 106, + "weight": 95, "cookies": false, "type": "", "demo": "projects\/update-auth-password-history.md", @@ -26589,7 +26661,8 @@ "limit": { "type": "integer", "description": "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 is20. Default value is 0", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26625,7 +26698,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 108, + "weight": 97, "cookies": false, "type": "", "demo": "projects\/update-personal-data-check.md", @@ -26705,7 +26778,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 101, + "weight": 90, "cookies": false, "type": "", "demo": "projects\/update-session-alerts.md", @@ -26785,7 +26858,7 @@ "x-appwrite": { "method": "updateSessionInvalidation", "group": "auth", - "weight": 137, + "weight": 126, "cookies": false, "type": "", "demo": "projects\/update-session-invalidation.md", @@ -26865,7 +26938,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 105, + "weight": 94, "cookies": false, "type": "", "demo": "projects\/update-auth-status.md", @@ -27346,7 +27419,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 123, + "weight": 112, "cookies": false, "type": "", "demo": "projects\/create-jwt.md", @@ -27457,7 +27530,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -27493,7 +27567,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 119, + "weight": 108, "cookies": false, "type": "", "demo": "projects\/list-keys.md", @@ -27563,7 +27637,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 118, + "weight": 107, "cookies": false, "type": "", "demo": "projects\/create-key.md", @@ -27718,7 +27792,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 120, + "weight": 109, "cookies": false, "type": "", "demo": "projects\/get-key.md", @@ -27787,7 +27861,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 121, + "weight": 110, "cookies": false, "type": "", "demo": "projects\/update-key.md", @@ -27943,7 +28017,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 122, + "weight": 111, "cookies": false, "type": "", "demo": "projects\/delete-key.md", @@ -28096,7 +28170,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 100, + "weight": 89, "cookies": false, "type": "", "demo": "projects\/update-o-auth-2.md", @@ -28239,7 +28313,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 125, + "weight": 114, "cookies": false, "type": "", "demo": "projects\/list-platforms.md", @@ -28309,7 +28383,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 124, + "weight": 113, "cookies": false, "type": "", "demo": "projects\/create-platform.md", @@ -28429,7 +28503,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 126, + "weight": 115, "cookies": false, "type": "", "demo": "projects\/get-platform.md", @@ -28498,7 +28572,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 127, + "weight": 116, "cookies": false, "type": "", "demo": "projects\/update-platform.md", @@ -28594,7 +28668,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 128, + "weight": 117, "cookies": false, "type": "", "demo": "projects\/delete-platform.md", @@ -28665,7 +28739,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 96, + "weight": 85, "cookies": false, "type": "", "demo": "projects\/update-service-status.md", @@ -28768,7 +28842,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 97, + "weight": 86, "cookies": false, "type": "", "demo": "projects\/update-service-status-all.md", @@ -28848,7 +28922,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 129, + "weight": 118, "cookies": false, "type": "", "demo": "projects\/update-smtp.md", @@ -28978,12 +29052,14 @@ "senderEmail": { "type": "string", "description": "Email of the sender", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -28993,7 +29069,8 @@ "port": { "type": "integer", "description": "SMTP server port", - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29043,7 +29120,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 130, + "weight": 119, "cookies": false, "type": "", "demo": "projects\/create-smtp-test.md", @@ -29180,12 +29257,14 @@ "senderEmail": { "type": "string", "description": "Email of the sender", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -29195,7 +29274,8 @@ "port": { "type": "integer", "description": "SMTP server port", - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29255,7 +29335,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 95, + "weight": 84, "cookies": false, "type": "", "demo": "projects\/update-team.md", @@ -29335,7 +29415,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 132, + "weight": 121, "cookies": false, "type": "", "demo": "projects\/get-email-template.md", @@ -29560,7 +29640,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 134, + "weight": 123, "cookies": false, "type": "", "demo": "projects\/update-email-template.md", @@ -29785,12 +29865,14 @@ "senderEmail": { "type": "string", "description": "Email of the sender", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -29825,7 +29907,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 136, + "weight": 125, "cookies": false, "type": "", "demo": "projects\/delete-email-template.md", @@ -30052,7 +30134,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 131, + "weight": 120, "cookies": false, "type": "", "demo": "projects\/get-sms-template.md", @@ -30338,7 +30420,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 133, + "weight": 122, "cookies": false, "type": "", "demo": "projects\/update-sms-template.md", @@ -30647,7 +30729,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 135, + "weight": 124, "cookies": false, "type": "", "demo": "projects\/delete-sms-template.md", @@ -30935,7 +31017,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 113, + "weight": 102, "cookies": false, "type": "", "demo": "projects\/list-webhooks.md", @@ -31005,7 +31087,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 112, + "weight": 101, "cookies": false, "type": "", "demo": "projects\/create-webhook.md", @@ -31121,7 +31203,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 114, + "weight": 103, "cookies": false, "type": "", "demo": "projects\/get-webhook.md", @@ -31190,7 +31272,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 115, + "weight": 104, "cookies": false, "type": "", "demo": "projects\/update-webhook.md", @@ -31307,7 +31389,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 117, + "weight": 106, "cookies": false, "type": "", "demo": "projects\/delete-webhook.md", @@ -31378,7 +31460,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 116, + "weight": 105, "cookies": false, "type": "", "demo": "projects\/update-webhook-signature.md", @@ -31715,7 +31797,8 @@ "url": { "type": "string", "description": "Target URL of redirection", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "statusCode": { "type": "string", @@ -32203,7 +32286,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -32884,7 +32968,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -33350,7 +33435,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -34820,7 +34906,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -35023,7 +35110,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -35302,7 +35390,8 @@ "file": { "type": "string", "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", - "x-example": null + "x-example": null, + "format": "binary" }, "permissions": { "type": "array", @@ -36413,7 +36502,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -38160,6 +38250,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -38276,6 +38367,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -38636,18 +38728,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -38764,18 +38859,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -38889,18 +38987,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -39017,18 +39118,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -40214,7 +40318,8 @@ "size": { "type": "integer", "description": "Column size for text columns, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -40353,6 +40458,7 @@ "type": "integer", "description": "Maximum size of the string column.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -40466,6 +40572,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -40582,6 +40689,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -42703,12 +42811,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -42829,12 +42939,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -43082,7 +43194,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -43171,7 +43283,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -43258,7 +43370,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -43322,7 +43434,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -43398,7 +43510,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -43464,7 +43576,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 157, + "weight": 146, "cookies": false, "type": "", "demo": "teams\/list-logs.md", @@ -43549,7 +43661,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -43648,7 +43760,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -43697,7 +43809,8 @@ "email": { "type": "string", "description": "Email of the new team member.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -43707,7 +43820,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -43727,7 +43841,8 @@ "url": { "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -43768,7 +43883,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -43842,7 +43957,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -43938,7 +44053,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -44014,7 +44129,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -44113,7 +44228,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -44175,7 +44290,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -44633,7 +44748,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -44719,7 +44834,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -44759,12 +44874,14 @@ "type": "string", "description": "User email.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -44811,7 +44928,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -44850,12 +44967,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44898,7 +45017,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -44937,12 +45056,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44985,7 +45106,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -45066,7 +45187,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -45129,7 +45250,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -45168,12 +45289,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45216,7 +45339,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -45255,12 +45378,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45303,7 +45428,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -45342,12 +45467,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45357,22 +45484,26 @@ "passwordCpu": { "type": "integer", "description": "Optional CPU cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -45420,7 +45551,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -45459,12 +45590,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45525,7 +45658,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -45564,12 +45697,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -45632,7 +45767,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 189, "cookies": false, "type": "", "demo": "users\/get-usage.md", @@ -45705,7 +45840,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -45759,7 +45894,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -45822,7 +45957,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -45868,7 +46003,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -45904,7 +46040,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -45955,7 +46091,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -45988,7 +46125,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -46073,7 +46210,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -46160,7 +46297,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -46258,7 +46395,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -46393,7 +46530,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -46529,7 +46666,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -46648,7 +46785,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -46765,7 +46902,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -46882,7 +47019,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -47001,7 +47138,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -47083,7 +47220,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -47165,7 +47302,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -47211,7 +47348,8 @@ "number": { "type": "string", "description": "User phone number.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -47247,7 +47385,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -47308,7 +47446,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -47390,7 +47528,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -47462,7 +47600,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -47516,7 +47654,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -47572,7 +47710,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -47645,7 +47783,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -47727,7 +47865,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -47812,7 +47950,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -47923,7 +48061,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -47994,7 +48132,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -48084,7 +48222,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -48157,7 +48295,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -48203,12 +48341,14 @@ "length": { "type": "integer", "description": "Token length in characters. The default length is 6 characters", - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -48241,7 +48381,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -48323,7 +48463,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -48405,7 +48545,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 204, + "weight": 193, "cookies": false, "type": "", "demo": "vcs\/create-repository-detection.md", @@ -48502,7 +48642,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 205, + "weight": 194, "cookies": false, "type": "", "demo": "vcs\/list-repositories.md", @@ -48601,7 +48741,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 206, + "weight": 195, "cookies": false, "type": "", "demo": "vcs\/create-repository.md", @@ -48687,7 +48827,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 207, + "weight": 196, "cookies": false, "type": "", "demo": "vcs\/get-repository.md", @@ -48758,7 +48898,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 208, + "weight": 197, "cookies": false, "type": "", "demo": "vcs\/list-repository-branches.md", @@ -48829,7 +48969,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 203, + "weight": 192, "cookies": false, "type": "", "demo": "vcs\/get-repository-contents.md", @@ -48915,7 +49055,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 213, + "weight": 202, "cookies": false, "type": "", "demo": "vcs\/update-external-deployments.md", @@ -49005,7 +49145,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 210, + "weight": 199, "cookies": false, "type": "", "demo": "vcs\/list-installations.md", @@ -49091,7 +49231,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 211, + "weight": 200, "cookies": false, "type": "", "demo": "vcs\/get-installation.md", @@ -49143,7 +49283,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 212, + "weight": 201, "cookies": false, "type": "", "demo": "vcs\/delete-installation.md", @@ -51111,14 +51251,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { @@ -52560,14 +52700,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 70e8b895ce..e82f3e5b78 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -142,7 +142,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -227,12 +228,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -445,7 +448,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -558,7 +562,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -631,7 +635,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -758,7 +762,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -901,7 +905,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1028,7 +1032,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1165,7 +1169,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1306,7 +1310,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1410,7 +1414,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1512,7 +1516,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1614,7 +1618,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1833,7 +1837,8 @@ "oldPassword": { "type": "string", "description": "Current user password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1906,12 +1911,14 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2113,12 +2120,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2428,12 +2437,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3001,7 +3012,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3088,12 +3100,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3321,7 +3335,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3449,7 +3464,8 @@ "url": { "type": "string", "description": "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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -3747,7 +3763,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -3877,7 +3893,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4013,7 +4029,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4075,7 +4091,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4567,7 +4583,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4653,7 +4669,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -4749,7 +4765,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -4845,7 +4861,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -5948,7 +5964,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7721,6 +7738,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -7839,6 +7857,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8205,18 +8224,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8335,18 +8357,21 @@ "type": "number", "description": "Minimum value.", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value.", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -8462,18 +8487,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -8592,18 +8620,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when attribute is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -9809,7 +9840,8 @@ "size": { "type": "integer", "description": "Attribute size for text attributes, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -9950,6 +9982,7 @@ "type": "integer", "description": "Maximum size of the string attribute.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10065,6 +10098,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10183,6 +10217,7 @@ "type": "string", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -11774,12 +11809,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -11903,12 +11940,14 @@ "value": { "type": "number", "description": "Value to increment the attribute by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12582,7 +12621,8 @@ "timeout": { "type": "integer", "description": "Function maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13048,7 +13088,8 @@ "timeout": { "type": "integer", "description": "Maximum execution time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13492,7 +13533,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -14876,7 +14918,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -14932,7 +14974,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -14988,7 +15030,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -15040,7 +15082,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -15092,7 +15134,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -15144,7 +15186,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -15207,7 +15249,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -15259,7 +15301,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -15311,7 +15353,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -15376,7 +15418,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -15441,7 +15483,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -15517,7 +15559,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -15582,7 +15624,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -15627,6 +15669,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -15673,7 +15716,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -15738,7 +15781,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -15803,7 +15846,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -15868,7 +15911,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -15933,7 +15976,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -15998,7 +16041,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -16063,7 +16106,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -16128,7 +16171,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -16193,7 +16236,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -16245,7 +16288,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -16297,7 +16340,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -16349,7 +16392,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -16405,7 +16448,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -16461,7 +16504,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -16517,7 +16560,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -16573,7 +16616,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -16629,7 +16672,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -16685,7 +16728,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -16741,7 +16784,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -16797,7 +16840,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -16886,7 +16929,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -17033,7 +17076,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -17192,7 +17235,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -17302,7 +17345,8 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -17370,7 +17414,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -17499,6 +17543,7 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS platforms.", "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -17568,7 +17613,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -17752,7 +17797,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -17942,7 +17987,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -17997,7 +18042,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -18061,7 +18106,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -18149,7 +18194,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -18237,7 +18282,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -18326,7 +18371,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -18508,7 +18553,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -18692,7 +18737,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -18847,7 +18892,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -19003,7 +19048,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -19069,7 +19114,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19079,7 +19125,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19122,7 +19169,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -19201,7 +19248,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19244,7 +19292,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -19342,7 +19390,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -19443,7 +19491,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -19498,7 +19546,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19508,7 +19557,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19551,7 +19601,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -19619,7 +19669,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19662,7 +19713,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -19717,7 +19768,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19727,7 +19779,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19770,7 +19823,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -19838,7 +19891,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19881,7 +19935,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -20019,7 +20073,8 @@ "port": { "type": "integer", "description": "The default SMTP server port.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -20061,7 +20116,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20071,7 +20127,8 @@ "replyToEmail": { "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20115,7 +20172,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -20257,6 +20314,7 @@ "type": "integer", "description": "SMTP port.", "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -20300,7 +20358,8 @@ "fromEmail": { "type": "string", "description": "Sender email address.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20349,7 +20408,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -20394,7 +20453,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -20447,7 +20507,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -20548,7 +20608,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -20593,7 +20653,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -20646,7 +20707,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -20747,7 +20808,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -20792,7 +20853,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -20845,7 +20907,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -20946,7 +21008,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -20991,7 +21053,8 @@ "from": { "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -21044,7 +21107,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -21145,7 +21208,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -21200,7 +21263,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -21264,7 +21327,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -21352,7 +21415,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -21440,7 +21503,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -21527,7 +21590,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -21612,7 +21675,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -21674,7 +21737,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -21755,7 +21818,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -21819,7 +21882,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -21907,7 +21970,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -22004,7 +22067,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -22097,7 +22160,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -22162,7 +22225,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -22404,7 +22467,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -22828,7 +22892,8 @@ "timeout": { "type": "integer", "description": "Maximum request time in seconds.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -23298,7 +23363,8 @@ "code": { "type": "string", "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", - "x-example": null + "x-example": null, + "format": "binary" }, "activate": { "type": "boolean", @@ -24703,7 +24769,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -24908,7 +24975,8 @@ "maximumFileSize": { "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -25192,7 +25260,8 @@ "file": { "type": "string", "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", - "x-example": null + "x-example": null, + "format": "binary" }, "permissions": { "type": "array", @@ -26165,7 +26234,8 @@ "ttl": { "type": "integer", "description": "Seconds before the transaction expires.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -27835,6 +27905,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -27952,6 +28023,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -28315,18 +28387,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -28444,18 +28519,21 @@ "type": "number", "description": "Minimum value", "x-example": null, + "format": "float", "x-nullable": true }, "max": { "type": "number", "description": "Maximum value", "x-example": null, + "format": "float", "x-nullable": true }, "default": { "type": "number", "description": "Default value. Cannot be set when required.", "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -28570,18 +28648,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -28699,18 +28780,21 @@ "type": "integer", "description": "Minimum value", "x-example": null, + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value", "x-example": null, + "format": "int64", "x-nullable": true }, "default": { "type": "integer", "description": "Default value. Cannot be set when column is required.", "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -29906,7 +29990,8 @@ "size": { "type": "integer", "description": "Column size for text columns, in number of characters.", - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -30046,6 +30131,7 @@ "type": "integer", "description": "Maximum size of the string column.", "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -30160,6 +30246,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -30277,6 +30364,7 @@ "type": "string", "description": "Default value for column when not provided. Cannot be set when column is required.", "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -32242,12 +32330,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32370,12 +32460,14 @@ "value": { "type": "number", "description": "Value to increment the column by. The value must be a number.", - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32415,7 +32507,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -32506,7 +32598,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -32595,7 +32687,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -32661,7 +32753,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -32739,7 +32831,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -32807,7 +32899,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -32908,7 +33000,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -32959,7 +33051,8 @@ "email": { "type": "string", "description": "Email of the new team member.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -32969,7 +33062,8 @@ "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -32989,7 +33083,8 @@ "url": { "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -33030,7 +33125,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -33106,7 +33201,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -33204,7 +33299,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -33282,7 +33377,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -33383,7 +33478,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -33447,7 +33542,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -33912,7 +34007,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -33999,7 +34094,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -34040,12 +34135,14 @@ "type": "string", "description": "User email.", "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -34092,7 +34189,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -34132,12 +34229,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34180,7 +34279,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -34220,12 +34319,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34268,7 +34369,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -34350,7 +34451,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -34414,7 +34515,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -34454,12 +34555,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34502,7 +34605,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -34542,12 +34645,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34590,7 +34695,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -34630,12 +34735,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34645,22 +34752,26 @@ "passwordCpu": { "type": "integer", "description": "Optional CPU cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -34708,7 +34819,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -34748,12 +34859,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34814,7 +34927,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -34854,12 +34967,14 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -34922,7 +35037,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -34977,7 +35092,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -35041,7 +35156,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -35088,7 +35203,8 @@ "email": { "type": "string", "description": "User email.", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -35124,7 +35240,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -35176,7 +35292,8 @@ "duration": { "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -35209,7 +35326,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -35295,7 +35412,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -35383,7 +35500,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -35482,7 +35599,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -35620,7 +35737,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -35759,7 +35876,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -35881,7 +35998,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -36001,7 +36118,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -36121,7 +36238,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -36243,7 +36360,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -36326,7 +36443,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -36409,7 +36526,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -36456,7 +36573,8 @@ "number": { "type": "string", "description": "User phone number.", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -36492,7 +36610,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -36554,7 +36672,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -36637,7 +36755,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -36710,7 +36828,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -36765,7 +36883,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -36822,7 +36940,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -36896,7 +37014,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -36979,7 +37097,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -37065,7 +37183,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -37177,7 +37295,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -37249,7 +37367,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -37340,7 +37458,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -37414,7 +37532,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -37461,12 +37579,14 @@ "length": { "type": "integer", "description": "Token length in characters. The default length is 6 characters", - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -37499,7 +37619,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -37582,7 +37702,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -39180,14 +39300,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { @@ -40629,14 +40749,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "nullable": true }, "default": { diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json index e11d5053a4..ae64cba59b 100644 --- a/app/config/specs/swagger2-1.8.x-client.json +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.8.0", + "version": "1.8.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -191,7 +191,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -280,13 +281,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -498,7 +501,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -608,7 +612,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -683,7 +687,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -807,7 +811,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -948,7 +952,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1072,7 +1076,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1209,7 +1213,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1349,7 +1353,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1450,7 +1454,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1551,7 +1555,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1652,7 +1656,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1874,7 +1878,8 @@ "type": "string", "description": "Current user password. Must be at least 8 chars.", "default": "", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1949,13 +1954,15 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2160,13 +2167,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2485,13 +2494,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3429,7 +3440,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3520,13 +3532,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3754,7 +3768,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3882,7 +3897,8 @@ "type": "string", "description": "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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4191,7 +4207,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4317,7 +4333,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4449,7 +4465,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4513,7 +4529,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -5001,7 +5017,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -5085,7 +5101,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5177,7 +5193,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5269,7 +5285,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -6087,7 +6103,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7208,13 +7225,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7329,13 +7348,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7375,7 +7396,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 454, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -7458,7 +7479,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 452, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -7577,7 +7598,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 453, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -7649,7 +7670,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -7724,7 +7745,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -7797,7 +7818,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -7850,7 +7871,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -7903,7 +7924,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -7956,7 +7977,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -8009,7 +8030,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -8062,7 +8083,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -8115,7 +8136,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -8168,7 +8189,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -8223,7 +8244,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -8308,7 +8329,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -8379,7 +8400,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 525, + "weight": 526, "cookies": false, "type": "", "demo": "storage\/list-files.md", @@ -8472,7 +8493,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 523, + "weight": 524, "cookies": false, "type": "upload", "demo": "storage\/create-file.md", @@ -8563,7 +8584,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 524, + "weight": 525, "cookies": false, "type": "", "demo": "storage\/get-file.md", @@ -8634,7 +8655,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 526, + "weight": 527, "cookies": false, "type": "", "demo": "storage\/update-file.md", @@ -8725,7 +8746,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 527, + "weight": 528, "cookies": false, "type": "", "demo": "storage\/delete-file.md", @@ -8796,7 +8817,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 529, + "weight": 530, "cookies": false, "type": "location", "demo": "storage\/get-file-download.md", @@ -8876,7 +8897,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 528, + "weight": 529, "cookies": false, "type": "location", "demo": "storage\/get-file-preview.md", @@ -9084,7 +9105,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 530, + "weight": 531, "cookies": false, "type": "location", "demo": "storage\/get-file-view.md", @@ -9275,7 +9296,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -10393,13 +10415,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10513,13 +10537,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10559,7 +10585,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -10644,7 +10670,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -10735,7 +10761,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -10798,7 +10824,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -10874,7 +10900,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -10937,7 +10963,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -11030,7 +11056,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -11076,7 +11102,8 @@ "type": "string", "description": "Email of the new team member.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -11088,7 +11115,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -11110,7 +11138,8 @@ "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -11151,7 +11180,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -11222,7 +11251,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -11316,7 +11345,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -11389,7 +11418,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -11485,7 +11514,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -11548,7 +11577,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index 21f8513e16..7672fc09d4 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.8.0", + "version": "1.8.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -201,7 +201,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -333,13 +334,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -548,7 +551,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -657,7 +661,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -731,7 +735,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -854,7 +858,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -994,7 +998,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1117,7 +1121,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1253,7 +1257,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1392,7 +1396,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1492,7 +1496,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1592,7 +1596,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1692,7 +1696,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1911,7 +1915,8 @@ "type": "string", "description": "Current user password. Must be at least 8 chars.", "default": "", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1985,13 +1990,15 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2193,13 +2200,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2513,13 +2522,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3445,7 +3456,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3535,13 +3547,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3767,7 +3781,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3894,7 +3909,8 @@ "type": "string", "description": "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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4200,7 +4216,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4326,7 +4342,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4458,7 +4474,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4522,7 +4538,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -5010,7 +5026,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -5094,7 +5110,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5186,7 +5202,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5278,7 +5294,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -5993,7 +6009,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 495, + "weight": 496, "cookies": false, "type": "", "demo": "assistant\/chat.md", @@ -6057,7 +6073,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 497, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -6128,7 +6144,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 494, + "weight": 495, "cookies": false, "type": "", "demo": "console\/variables.md", @@ -6518,7 +6534,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -8343,6 +8360,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -8457,6 +8475,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8819,6 +8838,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8826,6 +8846,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8833,6 +8854,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8947,6 +8969,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8954,6 +8977,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8961,6 +8985,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -9075,6 +9100,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -9082,6 +9108,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -9089,6 +9116,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -9203,6 +9231,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -9210,6 +9239,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -9217,6 +9247,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -10356,7 +10387,8 @@ "type": "integer", "description": "Attribute size for text attributes, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -10497,6 +10529,7 @@ "description": "Maximum size of the string attribute.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10611,6 +10644,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10725,6 +10759,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -12327,13 +12362,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12448,13 +12485,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -13275,7 +13314,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -13357,7 +13396,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 435, + "weight": 436, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -13505,7 +13544,8 @@ "type": "integer", "description": "Function maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13670,7 +13710,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -13720,7 +13760,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 441, + "weight": 442, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -13770,7 +13810,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 464, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/list-templates.md", @@ -13954,7 +13994,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 463, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/get-template.md", @@ -14012,7 +14052,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 457, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/list-usage.md", @@ -14082,7 +14122,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -14142,7 +14182,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -14292,7 +14332,8 @@ "type": "integer", "description": "Maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -14451,7 +14492,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -14513,7 +14554,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 444, + "weight": 445, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -14591,7 +14632,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 445, + "weight": 446, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -14681,7 +14722,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 442, + "weight": 443, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -14774,7 +14815,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 450, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -14860,7 +14901,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 447, + "weight": 448, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -14981,7 +15022,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 448, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -15078,7 +15119,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 443, + "weight": 444, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -15141,7 +15182,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 446, + "weight": 447, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -15209,7 +15250,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 449, + "weight": 450, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -15295,7 +15336,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 451, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -15363,7 +15404,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 454, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -15446,7 +15487,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 452, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -15565,7 +15606,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 453, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -15630,7 +15671,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 455, + "weight": 456, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -15698,7 +15739,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 456, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-usage.md", @@ -15776,7 +15817,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 460, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -15836,7 +15877,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 458, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -15927,7 +15968,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 459, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -15995,7 +16036,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 461, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -16090,7 +16131,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 462, + "weight": 463, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -16160,7 +16201,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -16235,7 +16276,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -16308,7 +16349,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -16359,7 +16400,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -16410,7 +16451,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -16461,7 +16502,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -16521,7 +16562,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -16572,7 +16613,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -16623,7 +16664,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -16685,7 +16726,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -16747,7 +16788,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -16818,7 +16859,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -16880,7 +16921,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -16923,6 +16964,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -16966,7 +17008,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -17028,7 +17070,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -17090,7 +17132,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -17152,7 +17194,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -17214,7 +17256,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -17276,7 +17318,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -17338,7 +17380,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -17400,7 +17442,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -17462,7 +17504,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -17513,7 +17555,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -17564,7 +17606,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -17615,7 +17657,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -17668,7 +17710,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -17721,7 +17763,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -17774,7 +17816,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -17827,7 +17869,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -17880,7 +17922,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -17933,7 +17975,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -17986,7 +18028,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -18039,7 +18081,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -18124,7 +18166,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -18284,7 +18326,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -18451,7 +18493,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -18575,7 +18617,8 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", "default": -1, - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -18649,7 +18692,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -18787,6 +18830,7 @@ "description": "Badge for push notification. Available only for iOS platforms.", "default": null, "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -18862,7 +18906,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -19052,7 +19096,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -19241,7 +19285,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -19297,7 +19341,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -19358,7 +19402,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -19440,7 +19484,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -19522,7 +19566,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -19607,7 +19651,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -19796,7 +19840,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -19982,7 +20026,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -20140,7 +20184,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -20294,7 +20338,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -20367,7 +20411,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20379,7 +20424,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20424,7 +20470,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -20506,7 +20552,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20552,7 +20599,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -20657,7 +20704,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -20760,7 +20807,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -20820,7 +20867,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20832,7 +20880,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20877,7 +20926,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -20946,7 +20995,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20992,7 +21042,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -21052,7 +21102,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21064,7 +21115,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21109,7 +21161,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -21178,7 +21230,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21224,7 +21277,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -21364,7 +21417,8 @@ "type": "integer", "description": "The default SMTP server port.", "default": 587, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -21413,7 +21467,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21425,7 +21480,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21471,7 +21527,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -21610,6 +21666,7 @@ "description": "SMTP port.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -21660,7 +21717,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21713,7 +21771,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -21761,7 +21819,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -21818,7 +21877,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -21921,7 +21980,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -21969,7 +22028,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -22026,7 +22086,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -22129,7 +22189,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -22177,7 +22237,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -22234,7 +22295,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -22337,7 +22398,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -22385,7 +22446,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -22442,7 +22504,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -22543,7 +22605,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -22599,7 +22661,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -22660,7 +22722,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -22742,7 +22804,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -22824,7 +22886,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -22907,7 +22969,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -22996,7 +23058,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -23057,7 +23119,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -23139,7 +23201,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -23200,7 +23262,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -23282,7 +23344,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -23373,7 +23435,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -23461,7 +23523,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -23525,7 +23587,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -23596,7 +23658,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 232, + "weight": 221, "cookies": false, "type": "", "demo": "migrations\/list.md", @@ -23679,7 +23741,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 226, + "weight": 215, "cookies": false, "type": "", "demo": "migrations\/create-appwrite-migration.md", @@ -23742,7 +23804,8 @@ "type": "string", "description": "Source Appwrite endpoint", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "projectId": { "type": "string", @@ -23792,7 +23855,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 234, + "weight": 223, "cookies": false, "type": "", "demo": "migrations\/get-appwrite-report.md", @@ -23901,7 +23964,7 @@ "x-appwrite": { "method": "createCSVExport", "group": null, - "weight": 231, + "weight": 220, "cookies": false, "type": "", "demo": "migrations\/create-csv-export.md", @@ -24027,7 +24090,7 @@ "x-appwrite": { "method": "createCSVImport", "group": null, - "weight": 230, + "weight": 219, "cookies": false, "type": "", "demo": "migrations\/create-csv-import.md", @@ -24118,7 +24181,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 227, + "weight": 216, "cookies": false, "type": "", "demo": "migrations\/create-firebase-migration.md", @@ -24211,7 +24274,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 235, + "weight": 224, "cookies": false, "type": "", "demo": "migrations\/get-firebase-report.md", @@ -24297,7 +24360,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 229, + "weight": 218, "cookies": false, "type": "", "demo": "migrations\/create-n-host-migration.md", @@ -24391,7 +24454,8 @@ "type": "integer", "description": "Source's Database Port", "default": 5432, - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24432,7 +24496,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 237, + "weight": 226, "cookies": false, "type": "", "demo": "migrations\/get-n-host-report.md", @@ -24568,7 +24632,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 228, + "weight": 217, "cookies": false, "type": "", "demo": "migrations\/create-supabase-migration.md", @@ -24626,7 +24690,8 @@ "type": "string", "description": "Source's Supabase Endpoint", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "apiKey": { "type": "string", @@ -24656,7 +24721,8 @@ "type": "integer", "description": "Source's Database Port", "default": 5432, - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24696,7 +24762,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 236, + "weight": 225, "cookies": false, "type": "", "demo": "migrations\/get-supabase-report.md", @@ -24823,7 +24889,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 233, + "weight": 222, "cookies": false, "type": "", "demo": "migrations\/get.md", @@ -24882,7 +24948,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 238, + "weight": 227, "cookies": false, "type": "", "demo": "migrations\/retry.md", @@ -24936,7 +25002,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 239, + "weight": 228, "cookies": false, "type": "", "demo": "migrations\/delete.md", @@ -24995,7 +25061,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 138, + "weight": 127, "cookies": false, "type": "", "demo": "project\/get-usage.md", @@ -25078,7 +25144,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 140, + "weight": 129, "cookies": false, "type": "", "demo": "project\/list-variables.md", @@ -25127,7 +25193,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 139, + "weight": 128, "cookies": false, "type": "", "demo": "project\/create-variable.md", @@ -25209,7 +25275,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 141, + "weight": 130, "cookies": false, "type": "", "demo": "project\/get-variable.md", @@ -25268,7 +25334,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 142, + "weight": 131, "cookies": false, "type": "", "demo": "project\/update-variable.md", @@ -25354,7 +25420,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 143, + "weight": 132, "cookies": false, "type": "", "demo": "project\/delete-variable.md", @@ -25438,7 +25504,7 @@ "parameters": [ { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search", "required": false, "type": "array", "collectionFormat": "multi", @@ -25493,7 +25559,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 92, + "weight": 81, "cookies": false, "type": "", "demo": "projects\/create.md", @@ -25568,7 +25634,8 @@ "type": "string", "description": "Project URL.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25641,7 +25708,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 93, + "weight": 82, "cookies": false, "type": "", "demo": "projects\/get.md", @@ -25700,7 +25767,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 94, + "weight": 83, "cookies": false, "type": "", "demo": "projects\/update.md", @@ -25760,7 +25827,8 @@ "type": "string", "description": "Project URL.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25826,7 +25894,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 111, + "weight": 100, "cookies": false, "type": "", "demo": "projects\/delete.md", @@ -25887,7 +25955,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 98, + "weight": 87, "cookies": false, "type": "", "demo": "projects\/update-api-status.md", @@ -26044,7 +26112,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 99, + "weight": 88, "cookies": false, "type": "", "demo": "projects\/update-api-status-all.md", @@ -26183,7 +26251,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 104, + "weight": 93, "cookies": false, "type": "", "demo": "projects\/update-auth-duration.md", @@ -26225,7 +26293,8 @@ "type": "integer", "description": "Project session length in seconds. Max length: 31536000 seconds.", "default": null, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26262,7 +26331,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 103, + "weight": 92, "cookies": false, "type": "", "demo": "projects\/update-auth-limit.md", @@ -26304,7 +26373,8 @@ "type": "integer", "description": "Set the max number of users allowed in this project. Use 0 for unlimited.", "default": null, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26341,7 +26411,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 109, + "weight": 98, "cookies": false, "type": "", "demo": "projects\/update-auth-sessions-limit.md", @@ -26383,7 +26453,8 @@ "type": "integer", "description": "Set the max number of users allowed in this project. Value allowed is between 1-100. Default is 10", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" } }, "required": [ @@ -26420,7 +26491,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 102, + "weight": 91, "cookies": false, "type": "", "demo": "projects\/update-memberships-privacy.md", @@ -26513,7 +26584,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 110, + "weight": 99, "cookies": false, "type": "", "demo": "projects\/update-mock-numbers.md", @@ -26595,7 +26666,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 107, + "weight": 96, "cookies": false, "type": "", "demo": "projects\/update-auth-password-dictionary.md", @@ -26674,7 +26745,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 106, + "weight": 95, "cookies": false, "type": "", "demo": "projects\/update-auth-password-history.md", @@ -26716,7 +26787,8 @@ "type": "integer", "description": "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 is20. Default value is 0", "default": null, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26753,7 +26825,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 108, + "weight": 97, "cookies": false, "type": "", "demo": "projects\/update-personal-data-check.md", @@ -26832,7 +26904,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 101, + "weight": 90, "cookies": false, "type": "", "demo": "projects\/update-session-alerts.md", @@ -26911,7 +26983,7 @@ "x-appwrite": { "method": "updateSessionInvalidation", "group": "auth", - "weight": 137, + "weight": 126, "cookies": false, "type": "", "demo": "projects\/update-session-invalidation.md", @@ -26990,7 +27062,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 105, + "weight": 94, "cookies": false, "type": "", "demo": "projects\/update-auth-status.md", @@ -27459,7 +27531,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 123, + "weight": 112, "cookies": false, "type": "", "demo": "projects\/create-jwt.md", @@ -27569,7 +27641,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -27604,7 +27677,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 119, + "weight": 108, "cookies": false, "type": "", "demo": "projects\/list-keys.md", @@ -27672,7 +27745,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 118, + "weight": 107, "cookies": false, "type": "", "demo": "projects\/create-key.md", @@ -27826,7 +27899,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 120, + "weight": 109, "cookies": false, "type": "", "demo": "projects\/get-key.md", @@ -27893,7 +27966,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 121, + "weight": 110, "cookies": false, "type": "", "demo": "projects\/update-key.md", @@ -28050,7 +28123,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 122, + "weight": 111, "cookies": false, "type": "", "demo": "projects\/delete-key.md", @@ -28093,6 +28166,87 @@ ] } }, + "\/projects\/{projectId}\/labels": { + "put": { + "summary": "Update project labels", + "operationId": "projectsUpdateLabels", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the project labels by its unique ID. Labels can be used to easily filter projects in an organization.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateLabels", + "group": "projects", + "weight": 435, + "cookies": false, + "type": "", + "demo": "projects\/update-labels.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "public": true, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "Array of project labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + } + } + ] + } + }, "\/projects\/{projectId}\/oauth2": { "patch": { "summary": "Update project OAuth2", @@ -28119,7 +28273,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 100, + "weight": 89, "cookies": false, "type": "", "demo": "projects\/update-o-auth-2.md", @@ -28262,7 +28416,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 125, + "weight": 114, "cookies": false, "type": "", "demo": "projects\/list-platforms.md", @@ -28330,7 +28484,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 124, + "weight": 113, "cookies": false, "type": "", "demo": "projects\/create-platform.md", @@ -28451,7 +28605,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 126, + "weight": 115, "cookies": false, "type": "", "demo": "projects\/get-platform.md", @@ -28518,7 +28672,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 127, + "weight": 116, "cookies": false, "type": "", "demo": "projects\/update-platform.md", @@ -28616,7 +28770,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 128, + "weight": 117, "cookies": false, "type": "", "demo": "projects\/delete-platform.md", @@ -28685,7 +28839,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 96, + "weight": 85, "cookies": false, "type": "", "demo": "projects\/update-service-status.md", @@ -28788,7 +28942,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 97, + "weight": 86, "cookies": false, "type": "", "demo": "projects\/update-service-status-all.md", @@ -28867,7 +29021,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 129, + "weight": 118, "cookies": false, "type": "", "demo": "projects\/update-smtp.md", @@ -28997,13 +29151,15 @@ "type": "string", "description": "Email of the sender", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -29015,7 +29171,8 @@ "type": "integer", "description": "SMTP server port", "default": 587, - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29073,7 +29230,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 130, + "weight": 119, "cookies": false, "type": "", "demo": "projects\/create-smtp-test.md", @@ -29210,13 +29367,15 @@ "type": "string", "description": "Email of the sender", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -29228,7 +29387,8 @@ "type": "integer", "description": "SMTP server port", "default": 587, - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29292,7 +29452,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 95, + "weight": 84, "cookies": false, "type": "", "demo": "projects\/update-team.md", @@ -29369,7 +29529,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 132, + "weight": 121, "cookies": false, "type": "", "demo": "projects\/get-email-template.md", @@ -29590,7 +29750,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 134, + "weight": 123, "cookies": false, "type": "", "demo": "projects\/update-email-template.md", @@ -29812,13 +29972,15 @@ "type": "string", "description": "Email of the sender", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -29854,7 +30016,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 136, + "weight": 125, "cookies": false, "type": "", "demo": "projects\/delete-email-template.md", @@ -30075,7 +30237,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 131, + "weight": 120, "cookies": false, "type": "", "demo": "projects\/get-sms-template.md", @@ -30357,7 +30519,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 133, + "weight": 122, "cookies": false, "type": "", "demo": "projects\/update-sms-template.md", @@ -30661,7 +30823,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 135, + "weight": 124, "cookies": false, "type": "", "demo": "projects\/delete-sms-template.md", @@ -30943,7 +31105,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 113, + "weight": 102, "cookies": false, "type": "", "demo": "projects\/list-webhooks.md", @@ -31011,7 +31173,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 112, + "weight": 101, "cookies": false, "type": "", "demo": "projects\/create-webhook.md", @@ -31130,7 +31292,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 114, + "weight": 103, "cookies": false, "type": "", "demo": "projects\/get-webhook.md", @@ -31197,7 +31359,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 115, + "weight": 104, "cookies": false, "type": "", "demo": "projects\/update-webhook.md", @@ -31319,7 +31481,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 117, + "weight": 106, "cookies": false, "type": "", "demo": "projects\/delete-webhook.md", @@ -31388,7 +31550,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 116, + "weight": 105, "cookies": false, "type": "", "demo": "projects\/update-webhook-signature.md", @@ -31455,7 +31617,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 510, + "weight": 511, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -31537,7 +31699,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 505, + "weight": 506, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -31607,7 +31769,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 507, + "weight": 508, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -31690,7 +31852,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 508, + "weight": 509, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -31729,7 +31891,8 @@ "type": "string", "description": "Target URL of redirection", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "statusCode": { "type": "string", @@ -31810,7 +31973,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 506, + "weight": 507, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -31891,7 +32054,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 509, + "weight": 510, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -31944,7 +32107,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 511, + "weight": 512, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -32004,7 +32167,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 512, + "weight": 513, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -32062,7 +32225,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 467, + "weight": 468, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -32144,7 +32307,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 465, + "weight": 466, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -32228,7 +32391,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -32415,7 +32579,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 470, + "weight": 471, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -32465,7 +32629,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 493, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -32515,7 +32679,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 489, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -32638,7 +32802,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 490, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -32696,7 +32860,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 491, + "weight": 492, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -32766,7 +32930,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 466, + "weight": 467, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -32826,7 +32990,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 468, + "weight": 469, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -32912,7 +33076,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -33092,7 +33257,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 469, + "weight": 470, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -33154,7 +33319,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 476, + "weight": 477, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -33232,7 +33397,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 475, + "weight": 476, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -33322,7 +33487,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 471, + "weight": 472, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -33423,7 +33588,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 479, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -33503,7 +33668,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 472, + "weight": 473, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -33624,7 +33789,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 473, + "weight": 474, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -33722,7 +33887,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 474, + "weight": 475, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -33785,7 +33950,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 477, + "weight": 478, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -33853,7 +34018,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 478, + "weight": 479, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -33939,7 +34104,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 480, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -34007,7 +34172,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 482, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -34088,7 +34253,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 481, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -34153,7 +34318,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -34221,7 +34386,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 492, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -34299,7 +34464,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -34359,7 +34524,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -34450,7 +34615,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -34518,7 +34683,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -34613,7 +34778,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -34681,7 +34846,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 520, + "weight": 521, "cookies": false, "type": "", "demo": "storage\/list-buckets.md", @@ -34764,7 +34929,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 518, + "weight": 519, "cookies": false, "type": "", "demo": "storage\/create-bucket.md", @@ -34834,7 +34999,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -34847,7 +35013,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "default": "none", "x-example": "none", "enum": [ @@ -34910,7 +35076,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 519, + "weight": 520, "cookies": false, "type": "", "demo": "storage\/get-bucket.md", @@ -34971,7 +35137,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 521, + "weight": 522, "cookies": false, "type": "", "demo": "storage\/update-bucket.md", @@ -35043,7 +35209,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -35056,7 +35223,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "default": "none", "x-example": "none", "enum": [ @@ -35113,7 +35280,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 522, + "weight": 523, "cookies": false, "type": "", "demo": "storage\/delete-bucket.md", @@ -35174,7 +35341,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 525, + "weight": 526, "cookies": false, "type": "", "demo": "storage\/list-files.md", @@ -35267,7 +35434,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 523, + "weight": 524, "cookies": false, "type": "upload", "demo": "storage\/create-file.md", @@ -35358,7 +35525,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 524, + "weight": 525, "cookies": false, "type": "", "demo": "storage\/get-file.md", @@ -35429,7 +35596,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 526, + "weight": 527, "cookies": false, "type": "", "demo": "storage\/update-file.md", @@ -35520,7 +35687,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 527, + "weight": 528, "cookies": false, "type": "", "demo": "storage\/delete-file.md", @@ -35591,7 +35758,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 529, + "weight": 530, "cookies": false, "type": "location", "demo": "storage\/get-file-download.md", @@ -35671,7 +35838,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 528, + "weight": 529, "cookies": false, "type": "location", "demo": "storage\/get-file-preview.md", @@ -35879,7 +36046,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 530, + "weight": 531, "cookies": false, "type": "location", "demo": "storage\/get-file-view.md", @@ -35959,7 +36126,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 532, + "weight": 533, "cookies": false, "type": "", "demo": "storage\/get-usage.md", @@ -36030,7 +36197,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 533, + "weight": 534, "cookies": false, "type": "", "demo": "storage\/get-bucket-usage.md", @@ -36387,7 +36554,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -38107,6 +38275,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -38220,6 +38389,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -38579,6 +38749,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -38586,6 +38757,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -38593,6 +38765,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -38706,6 +38879,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -38713,6 +38887,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -38720,6 +38895,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -38833,6 +39009,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -38840,6 +39017,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -38847,6 +39025,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -38960,6 +39139,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -38967,6 +39147,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -38974,6 +39155,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -40103,7 +40285,8 @@ "type": "integer", "description": "Column size for text columns, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -40243,6 +40426,7 @@ "description": "Maximum size of the string column.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -40356,6 +40540,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -40469,6 +40654,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -42508,13 +42694,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -42628,13 +42816,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -42872,7 +43062,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -42957,7 +43147,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -43048,7 +43238,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -43111,7 +43301,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -43187,7 +43377,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -43250,7 +43440,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 157, + "weight": 146, "cookies": false, "type": "", "demo": "teams\/list-logs.md", @@ -43330,7 +43520,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -43423,7 +43613,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -43469,7 +43659,8 @@ "type": "string", "description": "Email of the new team member.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -43481,7 +43672,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -43503,7 +43695,8 @@ "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -43544,7 +43737,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -43615,7 +43808,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -43709,7 +43902,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -43782,7 +43975,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -43877,7 +44070,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -43939,7 +44132,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -44019,7 +44212,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 515, + "weight": 516, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -44108,7 +44301,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 513, + "weight": 514, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -44192,7 +44385,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 514, + "weight": 515, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -44252,7 +44445,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 516, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -44323,7 +44516,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 517, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -44383,7 +44576,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -44466,7 +44659,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -44509,6 +44702,7 @@ "description": "User email.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { @@ -44516,6 +44710,7 @@ "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -44565,7 +44760,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -44607,13 +44802,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44658,7 +44855,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -44700,13 +44897,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44749,7 +44948,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -44829,7 +45028,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -44892,7 +45091,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -44934,13 +45133,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44985,7 +45186,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -45027,13 +45228,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45078,7 +45281,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -45120,13 +45323,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45138,25 +45343,29 @@ "type": "integer", "description": "Optional CPU cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -45206,7 +45415,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -45248,13 +45457,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45320,7 +45531,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -45362,13 +45573,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -45432,7 +45645,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 189, "cookies": false, "type": "", "demo": "users\/get-usage.md", @@ -45503,7 +45716,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -45559,7 +45772,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -45622,7 +45835,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -45666,7 +45879,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -45703,7 +45917,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -45753,7 +45967,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -45787,7 +46002,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -45869,7 +46084,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -45951,7 +46166,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -46044,7 +46259,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -46180,7 +46395,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -46312,7 +46527,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -46429,7 +46644,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -46546,7 +46761,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -46663,7 +46878,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -46782,7 +46997,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -46863,7 +47078,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -46944,7 +47159,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -46988,7 +47203,8 @@ "type": "string", "description": "User phone number.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -47023,7 +47239,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -47084,7 +47300,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -47163,7 +47379,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -47233,7 +47449,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -47289,7 +47505,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -47347,7 +47563,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -47418,7 +47634,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -47497,7 +47713,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -47579,7 +47795,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -47691,7 +47907,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -47760,7 +47976,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -47851,7 +48067,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -47922,7 +48138,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -47966,13 +48182,15 @@ "type": "integer", "description": "Token length in characters. The default length is 6 characters", "default": 6, - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", "default": 900, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -48006,7 +48224,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -48087,7 +48305,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -48168,7 +48386,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 204, + "weight": 193, "cookies": false, "type": "", "demo": "vcs\/create-repository-detection.md", @@ -48264,7 +48482,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 205, + "weight": 194, "cookies": false, "type": "", "demo": "vcs\/list-repositories.md", @@ -48358,7 +48576,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 206, + "weight": 195, "cookies": false, "type": "", "demo": "vcs\/create-repository.md", @@ -48442,7 +48660,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 207, + "weight": 196, "cookies": false, "type": "", "demo": "vcs\/get-repository.md", @@ -48509,7 +48727,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 208, + "weight": 197, "cookies": false, "type": "", "demo": "vcs\/list-repository-branches.md", @@ -48576,7 +48794,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 203, + "weight": 192, "cookies": false, "type": "", "demo": "vcs\/get-repository-contents.md", @@ -48660,7 +48878,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 213, + "weight": 202, "cookies": false, "type": "", "demo": "vcs\/update-external-deployments.md", @@ -48745,7 +48963,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 210, + "weight": 199, "cookies": false, "type": "", "demo": "vcs\/list-installations.md", @@ -48826,7 +49044,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 211, + "weight": 200, "cookies": false, "type": "", "demo": "vcs\/get-installation.md", @@ -48880,7 +49098,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 212, + "weight": 201, "cookies": false, "type": "", "demo": "vcs\/delete-installation.md", @@ -50858,14 +51076,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { @@ -52308,14 +52526,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { @@ -54901,7 +55119,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "description": "Compression algorithm chosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", "x-example": "gzip" }, "encryption": { @@ -54918,6 +55136,12 @@ "type": "boolean", "description": "Image transformations are enabled.", "x-example": false + }, + "totalSize": { + "type": "integer", + "description": "Total size of this bucket in bytes.", + "x-example": 128, + "format": "int32" } }, "required": [ @@ -54933,7 +55157,8 @@ "compression", "encryption", "antivirus", - "transformations" + "transformations", + "totalSize" ], "example": { "$id": "5e5ea5c16897e", @@ -54953,7 +55178,8 @@ "compression": "gzip", "encryption": false, "antivirus": false, - "transformations": false + "transformations": false, + "totalSize": 128 } }, "resourceToken": { @@ -57338,6 +57564,16 @@ "description": "Last ping datetime in ISO 8601 format.", "x-example": "2020-10-15T06:38:00.000+00:00" }, + "labels": { + "type": "array", + "description": "Labels for the project.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, "authEmailPassword": { "type": "boolean", "description": "Email\/Password auth method status", @@ -57482,6 +57718,7 @@ "smtpSecure", "pingCount", "pingedAt", + "labels", "authEmailPassword", "authUsersAuthMagicURL", "authEmailOtp", @@ -57550,6 +57787,9 @@ "smtpSecure": "tls", "pingCount": 1, "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [ + "vip" + ], "authEmailPassword": true, "authUsersAuthMagicURL": true, "authEmailOtp": true, @@ -59551,171 +59791,6 @@ "description": "Time range of the usage stats.", "x-example": "30d" }, - "deploymentsTotal": { - "type": "integer", - "description": "Total aggregated number of functions deployments.", - "x-example": 0, - "format": "int32" - }, - "deploymentsStorageTotal": { - "type": "integer", - "description": "Total aggregated sum of functions deployment storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTotal": { - "type": "integer", - "description": "Total aggregated number of functions build.", - "x-example": 0, - "format": "int32" - }, - "buildsStorageTotal": { - "type": "integer", - "description": "total aggregated sum of functions build storage.", - "x-example": 0, - "format": "int32" - }, - "buildsTimeTotal": { - "type": "integer", - "description": "Total aggregated sum of functions build compute time.", - "x-example": 0, - "format": "int32" - }, - "buildsMbSecondsTotal": { - "type": "integer", - "description": "Total aggregated sum of functions build mbSeconds.", - "x-example": 0, - "format": "int32" - }, - "executionsTotal": { - "type": "integer", - "description": "Total aggregated number of functions execution.", - "x-example": 0, - "format": "int32" - }, - "executionsTimeTotal": { - "type": "integer", - "description": "Total aggregated sum of functions execution compute time.", - "x-example": 0, - "format": "int32" - }, - "executionsMbSecondsTotal": { - "type": "integer", - "description": "Total aggregated sum of functions execution mbSeconds.", - "x-example": 0, - "format": "int32" - }, - "deployments": { - "type": "array", - "description": "Aggregated number of functions deployment per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "deploymentsStorage": { - "type": "array", - "description": "Aggregated number of functions deployment storage per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsSuccessTotal": { - "type": "integer", - "description": "Total aggregated number of successful function builds.", - "x-example": 0, - "format": "int32" - }, - "buildsFailedTotal": { - "type": "integer", - "description": "Total aggregated number of failed function builds.", - "x-example": 0, - "format": "int32" - }, - "builds": { - "type": "array", - "description": "Aggregated number of functions build per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsStorage": { - "type": "array", - "description": "Aggregated sum of functions build storage per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsTime": { - "type": "array", - "description": "Aggregated sum of functions build compute time per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsMbSeconds": { - "type": "array", - "description": "Aggregated sum of functions build mbSeconds per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "executions": { - "type": "array", - "description": "Aggregated number of functions execution per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "executionsTime": { - "type": "array", - "description": "Aggregated number of functions execution compute time per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "executionsMbSeconds": { - "type": "array", - "description": "Aggregated number of functions mbSeconds per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsSuccess": { - "type": "array", - "description": "Aggregated number of successful function builds per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, - "buildsFailed": { - "type": "array", - "description": "Aggregated number of failed function builds per period.", - "items": { - "type": "object", - "$ref": "#\/definitions\/metric" - }, - "x-example": [] - }, "sitesTotal": { "type": "integer", "description": "Total aggregated number of sites.", @@ -59731,6 +59806,60 @@ }, "x-example": [] }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of sites deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of sites deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of sites build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of sites build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of sites execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of sites execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of sites execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, "requestsTotal": { "type": "integer", "description": "Total aggregated number of requests.", @@ -59775,10 +59904,123 @@ "$ref": "#\/definitions\/metric" }, "x-example": [] + }, + "deployments": { + "type": "array", + "description": "Aggregated number of sites deployment per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of sites deployment storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful site builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed site builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of sites build per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of sites build storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of sites build compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of sites build mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of sites execution per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of sites execution compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of sites mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful site builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed site builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] } }, "required": [ "range", + "sitesTotal", + "sites", "deploymentsTotal", "deploymentsStorageTotal", "buildsTotal", @@ -59788,6 +60030,12 @@ "executionsTotal", "executionsTimeTotal", "executionsMbSecondsTotal", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound", "deployments", "deploymentsStorage", "buildsSuccessTotal", @@ -59800,18 +60048,12 @@ "executionsTime", "executionsMbSeconds", "buildsSuccess", - "buildsFailed", - "sitesTotal", - "sites", - "requestsTotal", - "requests", - "inboundTotal", - "inbound", - "outboundTotal", - "outbound" + "buildsFailed" ], "example": { "range": "30d", + "sitesTotal": 0, + "sites": [], "deploymentsTotal": 0, "deploymentsStorageTotal": 0, "buildsTotal": 0, @@ -59821,6 +60063,12 @@ "executionsTotal": 0, "executionsTimeTotal": 0, "executionsMbSecondsTotal": 0, + "requestsTotal": 0, + "requests": [], + "inboundTotal": 0, + "inbound": [], + "outboundTotal": 0, + "outbound": [], "deployments": [], "deploymentsStorage": [], "buildsSuccessTotal": 0, @@ -59833,15 +60081,7 @@ "executionsTime": [], "executionsMbSeconds": [], "buildsSuccess": [], - "buildsFailed": [], - "sitesTotal": 0, - "sites": [], - "requestsTotal": 0, - "requests": [], - "inboundTotal": 0, - "inbound": [], - "outboundTotal": 0, - "outbound": [] + "buildsFailed": [] } }, "usageSite": { diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index a3d51a703d..284c917919 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.8.0", + "version": "1.8.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -202,7 +202,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -292,13 +293,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -513,7 +516,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -624,7 +628,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -700,7 +704,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -827,7 +831,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -971,7 +975,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1098,7 +1102,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1238,7 +1242,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1381,7 +1385,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1485,7 +1489,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1589,7 +1593,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1693,7 +1697,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1920,7 +1924,8 @@ "type": "string", "description": "Current user password. Must be at least 8 chars.", "default": "", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1996,13 +2001,15 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2210,13 +2217,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2540,13 +2549,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3132,7 +3143,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3224,13 +3236,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3460,7 +3474,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3591,7 +3606,8 @@ "type": "string", "description": "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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -3905,7 +3921,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4033,7 +4049,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4167,7 +4183,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4233,7 +4249,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4723,7 +4739,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4809,7 +4825,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -4903,7 +4919,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -4997,7 +5013,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -6061,7 +6077,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7809,6 +7826,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -7924,6 +7942,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8289,6 +8308,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8296,6 +8316,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8303,6 +8324,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8418,6 +8440,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8425,6 +8448,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8432,6 +8456,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -8547,6 +8572,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -8554,6 +8580,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -8561,6 +8588,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -8676,6 +8704,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -8683,6 +8712,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -8690,6 +8720,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -9839,7 +9870,8 @@ "type": "integer", "description": "Attribute size for text attributes, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -9981,6 +10013,7 @@ "description": "Maximum size of the string attribute.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10096,6 +10129,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10211,6 +10245,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -11746,13 +11781,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -11869,13 +11906,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12308,7 +12347,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -12391,7 +12430,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 435, + "weight": 436, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -12540,7 +12579,8 @@ "type": "integer", "description": "Function maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -12705,7 +12745,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -12756,7 +12796,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 441, + "weight": 442, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -12807,7 +12847,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -12868,7 +12908,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -13019,7 +13059,8 @@ "type": "integer", "description": "Maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13178,7 +13219,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -13241,7 +13282,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 444, + "weight": 445, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -13320,7 +13361,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 445, + "weight": 446, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -13411,7 +13452,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 442, + "weight": 443, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -13505,7 +13546,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 450, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -13592,7 +13633,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 447, + "weight": 448, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -13714,7 +13755,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 448, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -13812,7 +13853,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 443, + "weight": 444, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -13876,7 +13917,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 446, + "weight": 447, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -13945,7 +13986,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 449, + "weight": 450, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -14032,7 +14073,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 451, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -14101,7 +14142,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 454, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -14186,7 +14227,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 452, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -14307,7 +14348,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 453, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -14374,7 +14415,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 455, + "weight": 456, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -14443,7 +14484,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 460, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -14504,7 +14545,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 458, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -14596,7 +14637,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 459, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -14665,7 +14706,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 461, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -14761,7 +14802,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 462, + "weight": 463, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -14832,7 +14873,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -14909,7 +14950,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -14984,7 +15025,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -15036,7 +15077,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -15088,7 +15129,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -15140,7 +15181,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -15201,7 +15242,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -15253,7 +15294,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -15305,7 +15346,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -15368,7 +15409,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -15431,7 +15472,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -15503,7 +15544,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -15566,7 +15607,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -15610,6 +15651,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -15653,7 +15695,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -15716,7 +15758,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -15779,7 +15821,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -15842,7 +15884,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -15905,7 +15947,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -15968,7 +16010,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -16031,7 +16073,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -16094,7 +16136,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -16157,7 +16199,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -16209,7 +16251,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -16261,7 +16303,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -16313,7 +16355,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -16368,7 +16410,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -16423,7 +16465,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -16478,7 +16520,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -16533,7 +16575,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -16588,7 +16630,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -16643,7 +16685,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -16698,7 +16740,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -16753,7 +16795,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -16839,7 +16881,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -17000,7 +17042,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -17168,7 +17210,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -17293,7 +17335,8 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", "default": -1, - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -17367,7 +17410,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -17506,6 +17549,7 @@ "description": "Badge for push notification. Available only for iOS platforms.", "default": null, "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -17581,7 +17625,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -17774,7 +17818,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -17966,7 +18010,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -18023,7 +18067,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -18085,7 +18129,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -18168,7 +18212,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -18251,7 +18295,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -18337,7 +18381,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -18529,7 +18573,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -18718,7 +18762,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -18879,7 +18923,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -19036,7 +19080,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -19110,7 +19154,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19122,7 +19167,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19167,7 +19213,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -19250,7 +19296,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19296,7 +19343,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -19402,7 +19449,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -19506,7 +19553,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -19567,7 +19614,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19579,7 +19627,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19624,7 +19673,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -19694,7 +19743,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19740,7 +19790,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -19801,7 +19851,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19813,7 +19864,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19858,7 +19910,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -19928,7 +19980,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19974,7 +20027,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -20117,7 +20170,8 @@ "type": "integer", "description": "The default SMTP server port.", "default": 587, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -20166,7 +20220,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20178,7 +20233,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20224,7 +20280,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -20366,6 +20422,7 @@ "description": "SMTP port.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -20416,7 +20473,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20469,7 +20527,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -20518,7 +20576,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -20575,7 +20634,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -20679,7 +20738,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -20728,7 +20787,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -20785,7 +20845,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -20889,7 +20949,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -20938,7 +20998,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -20995,7 +21056,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -21099,7 +21160,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -21148,7 +21209,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -21205,7 +21267,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -21307,7 +21369,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -21364,7 +21426,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -21426,7 +21488,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -21509,7 +21571,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -21592,7 +21654,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -21676,7 +21738,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -21766,7 +21828,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -21828,7 +21890,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -21911,7 +21973,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -21973,7 +22035,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -22056,7 +22118,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -22148,7 +22210,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -22238,7 +22300,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -22303,7 +22365,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -22376,7 +22438,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 467, + "weight": 468, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -22459,7 +22521,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 465, + "weight": 466, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -22544,7 +22606,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -22731,7 +22794,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 470, + "weight": 471, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -22782,7 +22845,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 493, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -22833,7 +22896,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 466, + "weight": 467, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -22894,7 +22957,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 468, + "weight": 469, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -22981,7 +23044,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -23161,7 +23225,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 469, + "weight": 470, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -23224,7 +23288,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 476, + "weight": 477, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -23303,7 +23367,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 475, + "weight": 476, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -23394,7 +23458,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 471, + "weight": 472, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -23496,7 +23560,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 479, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -23577,7 +23641,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 472, + "weight": 473, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -23699,7 +23763,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 473, + "weight": 474, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -23798,7 +23862,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 474, + "weight": 475, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -23862,7 +23926,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 477, + "weight": 478, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -23931,7 +23995,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 478, + "weight": 479, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -24018,7 +24082,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 480, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -24087,7 +24151,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 482, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -24169,7 +24233,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 481, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -24235,7 +24299,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -24304,7 +24368,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -24365,7 +24429,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -24457,7 +24521,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -24526,7 +24590,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -24622,7 +24686,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -24691,7 +24755,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 520, + "weight": 521, "cookies": false, "type": "", "demo": "storage\/list-buckets.md", @@ -24775,7 +24839,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 518, + "weight": 519, "cookies": false, "type": "", "demo": "storage\/create-bucket.md", @@ -24846,7 +24910,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -24859,7 +24924,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "default": "none", "x-example": "none", "enum": [ @@ -24922,7 +24987,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 519, + "weight": 520, "cookies": false, "type": "", "demo": "storage\/get-bucket.md", @@ -24984,7 +25049,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 521, + "weight": 522, "cookies": false, "type": "", "demo": "storage\/update-bucket.md", @@ -25057,7 +25122,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -25070,7 +25136,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "description": "Compression algorithm chosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", "default": "none", "x-example": "none", "enum": [ @@ -25127,7 +25193,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 522, + "weight": 523, "cookies": false, "type": "", "demo": "storage\/delete-bucket.md", @@ -25189,7 +25255,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 525, + "weight": 526, "cookies": false, "type": "", "demo": "storage\/list-files.md", @@ -25284,7 +25350,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 523, + "weight": 524, "cookies": false, "type": "upload", "demo": "storage\/create-file.md", @@ -25377,7 +25443,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 524, + "weight": 525, "cookies": false, "type": "", "demo": "storage\/get-file.md", @@ -25450,7 +25516,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 526, + "weight": 527, "cookies": false, "type": "", "demo": "storage\/update-file.md", @@ -25543,7 +25609,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 527, + "weight": 528, "cookies": false, "type": "", "demo": "storage\/delete-file.md", @@ -25616,7 +25682,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 529, + "weight": 530, "cookies": false, "type": "location", "demo": "storage\/get-file-download.md", @@ -25698,7 +25764,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 528, + "weight": 529, "cookies": false, "type": "location", "demo": "storage\/get-file-preview.md", @@ -25908,7 +25974,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 530, + "weight": 531, "cookies": false, "type": "location", "demo": "storage\/get-file-view.md", @@ -26274,7 +26340,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -27919,6 +27986,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -28033,6 +28101,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -28395,6 +28464,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -28402,6 +28472,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -28409,6 +28480,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -28523,6 +28595,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -28530,6 +28603,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -28537,6 +28611,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -28651,6 +28726,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -28658,6 +28734,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -28665,6 +28742,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -28779,6 +28857,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -28786,6 +28865,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -28793,6 +28873,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -29932,7 +30013,8 @@ "type": "integer", "description": "Column size for text columns, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -30073,6 +30155,7 @@ "description": "Maximum size of the string column.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -30187,6 +30270,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -30301,6 +30385,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -32196,13 +32281,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32318,13 +32405,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32364,7 +32453,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -32451,7 +32540,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -32544,7 +32633,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -32609,7 +32698,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -32687,7 +32776,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -32752,7 +32841,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -32847,7 +32936,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -32895,7 +32984,8 @@ "type": "string", "description": "Email of the new team member.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -32907,7 +32997,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -32929,7 +33020,8 @@ "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -32970,7 +33062,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -33043,7 +33135,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -33139,7 +33231,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -33214,7 +33306,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -33311,7 +33403,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -33375,7 +33467,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -33457,7 +33549,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 515, + "weight": 516, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -33547,7 +33639,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 513, + "weight": 514, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -33632,7 +33724,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 514, + "weight": 515, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -33693,7 +33785,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 516, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -33765,7 +33857,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 517, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -33826,7 +33918,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -33910,7 +34002,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -33954,6 +34046,7 @@ "description": "User email.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { @@ -33961,6 +34054,7 @@ "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -34010,7 +34104,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -34053,13 +34147,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34104,7 +34200,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -34147,13 +34243,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34196,7 +34294,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -34277,7 +34375,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -34341,7 +34439,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -34384,13 +34482,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34435,7 +34535,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -34478,13 +34578,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34529,7 +34631,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -34572,13 +34674,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34590,25 +34694,29 @@ "type": "integer", "description": "Optional CPU cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -34658,7 +34766,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -34701,13 +34809,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34773,7 +34883,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -34816,13 +34926,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -34886,7 +34998,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -34943,7 +35055,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -35007,7 +35119,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -35052,7 +35164,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -35089,7 +35202,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -35140,7 +35253,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -35174,7 +35288,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -35257,7 +35371,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -35340,7 +35454,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -35434,7 +35548,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -35573,7 +35687,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -35708,7 +35822,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -35828,7 +35942,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -35948,7 +36062,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -36068,7 +36182,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -36190,7 +36304,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -36272,7 +36386,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -36354,7 +36468,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -36399,7 +36513,8 @@ "type": "string", "description": "User phone number.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -36434,7 +36549,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -36496,7 +36611,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -36576,7 +36691,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -36647,7 +36762,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -36704,7 +36819,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -36763,7 +36878,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -36835,7 +36950,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -36915,7 +37030,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -36998,7 +37113,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -37111,7 +37226,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -37181,7 +37296,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -37273,7 +37388,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -37345,7 +37460,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -37390,13 +37505,15 @@ "type": "integer", "description": "Token length in characters. The default length is 6 characters", "default": 6, - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", "default": 900, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -37430,7 +37547,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -37512,7 +37629,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -39105,14 +39222,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { @@ -40555,14 +40672,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { @@ -43148,7 +43265,7 @@ }, "compression": { "type": "string", - "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "description": "Compression algorithm chosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", "x-example": "gzip" }, "encryption": { @@ -43165,6 +43282,12 @@ "type": "boolean", "description": "Image transformations are enabled.", "x-example": false + }, + "totalSize": { + "type": "integer", + "description": "Total size of this bucket in bytes.", + "x-example": 128, + "format": "int32" } }, "required": [ @@ -43180,7 +43303,8 @@ "compression", "encryption", "antivirus", - "transformations" + "transformations", + "totalSize" ], "example": { "$id": "5e5ea5c16897e", @@ -43200,7 +43324,8 @@ "compression": "gzip", "encryption": false, "antivirus": false, - "transformations": false + "transformations": false, + "totalSize": 128 } }, "resourceToken": { diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 07889bba5e..ae64cba59b 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -191,7 +191,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -280,13 +281,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -498,7 +501,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -608,7 +612,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -683,7 +687,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -807,7 +811,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -948,7 +952,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1072,7 +1076,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1209,7 +1213,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1349,7 +1353,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1450,7 +1454,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1551,7 +1555,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1652,7 +1656,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1874,7 +1878,8 @@ "type": "string", "description": "Current user password. Must be at least 8 chars.", "default": "", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1949,13 +1954,15 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2160,13 +2167,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2485,13 +2494,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3429,7 +3440,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3520,13 +3532,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3754,7 +3768,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3882,7 +3897,8 @@ "type": "string", "description": "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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4191,7 +4207,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4317,7 +4333,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4449,7 +4465,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4513,7 +4529,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -5001,7 +5017,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -5085,7 +5101,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5177,7 +5193,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5269,7 +5285,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -6087,7 +6103,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7208,13 +7225,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7329,13 +7348,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -7649,7 +7670,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -7724,7 +7745,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -7797,7 +7818,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -7850,7 +7871,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -7903,7 +7924,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -7956,7 +7977,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -8009,7 +8030,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -8062,7 +8083,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -8115,7 +8136,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -8168,7 +8189,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -8223,7 +8244,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -8308,7 +8329,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -9275,7 +9296,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -10393,13 +10415,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10513,13 +10537,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -10559,7 +10585,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -10644,7 +10670,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -10735,7 +10761,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -10798,7 +10824,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -10874,7 +10900,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -10937,7 +10963,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -11030,7 +11056,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -11076,7 +11102,8 @@ "type": "string", "description": "Email of the new team member.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -11088,7 +11115,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -11110,7 +11138,8 @@ "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -11151,7 +11180,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -11222,7 +11251,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -11316,7 +11345,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -11389,7 +11418,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -11485,7 +11514,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -11548,7 +11577,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 4b384cae76..7672fc09d4 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -201,7 +201,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -333,13 +334,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -548,7 +551,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -657,7 +661,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -731,7 +735,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -854,7 +858,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -994,7 +998,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1117,7 +1121,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1253,7 +1257,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1392,7 +1396,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1492,7 +1496,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1592,7 +1596,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1692,7 +1696,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1911,7 +1915,8 @@ "type": "string", "description": "Current user password. Must be at least 8 chars.", "default": "", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1985,13 +1990,15 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2193,13 +2200,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2513,13 +2522,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3445,7 +3456,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3535,13 +3547,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3767,7 +3781,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3894,7 +3909,8 @@ "type": "string", "description": "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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -4200,7 +4216,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4326,7 +4342,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4458,7 +4474,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4522,7 +4538,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -5010,7 +5026,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -5094,7 +5110,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -5186,7 +5202,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -5278,7 +5294,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -6518,7 +6534,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -8343,6 +8360,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -8457,6 +8475,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8819,6 +8838,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8826,6 +8846,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8833,6 +8854,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8947,6 +8969,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8954,6 +8977,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8961,6 +8985,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -9075,6 +9100,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -9082,6 +9108,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -9089,6 +9116,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -9203,6 +9231,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -9210,6 +9239,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -9217,6 +9247,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -10356,7 +10387,8 @@ "type": "integer", "description": "Attribute size for text attributes, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -10497,6 +10529,7 @@ "description": "Maximum size of the string attribute.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10611,6 +10644,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10725,6 +10759,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -12327,13 +12362,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12448,13 +12485,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -13505,7 +13544,8 @@ "type": "integer", "description": "Function maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -14292,7 +14332,8 @@ "type": "integer", "description": "Maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -16160,7 +16201,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -16235,7 +16276,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -16308,7 +16349,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -16359,7 +16400,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -16410,7 +16451,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -16461,7 +16502,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -16521,7 +16562,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -16572,7 +16613,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -16623,7 +16664,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -16685,7 +16726,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -16747,7 +16788,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -16818,7 +16859,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -16880,7 +16921,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -16923,6 +16964,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -16966,7 +17008,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -17028,7 +17070,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -17090,7 +17132,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -17152,7 +17194,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -17214,7 +17256,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -17276,7 +17318,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -17338,7 +17380,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -17400,7 +17442,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -17462,7 +17504,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -17513,7 +17555,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -17564,7 +17606,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -17615,7 +17657,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -17668,7 +17710,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -17721,7 +17763,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -17774,7 +17816,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -17827,7 +17869,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -17880,7 +17922,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -17933,7 +17975,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -17986,7 +18028,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -18039,7 +18081,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -18124,7 +18166,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -18284,7 +18326,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -18451,7 +18493,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -18575,7 +18617,8 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", "default": -1, - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -18649,7 +18692,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -18787,6 +18830,7 @@ "description": "Badge for push notification. Available only for iOS platforms.", "default": null, "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -18862,7 +18906,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -19052,7 +19096,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -19241,7 +19285,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -19297,7 +19341,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -19358,7 +19402,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -19440,7 +19484,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -19522,7 +19566,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -19607,7 +19651,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -19796,7 +19840,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -19982,7 +20026,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -20140,7 +20184,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -20294,7 +20338,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -20367,7 +20411,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20379,7 +20424,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20424,7 +20470,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -20506,7 +20552,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20552,7 +20599,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -20657,7 +20704,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -20760,7 +20807,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -20820,7 +20867,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20832,7 +20880,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20877,7 +20926,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -20946,7 +20995,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20992,7 +21042,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -21052,7 +21102,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21064,7 +21115,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21109,7 +21161,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -21178,7 +21230,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21224,7 +21277,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -21364,7 +21417,8 @@ "type": "integer", "description": "The default SMTP server port.", "default": 587, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -21413,7 +21467,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21425,7 +21480,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -21471,7 +21527,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -21610,6 +21666,7 @@ "description": "SMTP port.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -21660,7 +21717,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -21713,7 +21771,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -21761,7 +21819,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -21818,7 +21877,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -21921,7 +21980,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -21969,7 +22028,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -22026,7 +22086,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -22129,7 +22189,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -22177,7 +22237,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -22234,7 +22295,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -22337,7 +22398,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -22385,7 +22446,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -22442,7 +22504,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -22543,7 +22605,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -22599,7 +22661,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -22660,7 +22722,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -22742,7 +22804,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -22824,7 +22886,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -22907,7 +22969,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -22996,7 +23058,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -23057,7 +23119,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -23139,7 +23201,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -23200,7 +23262,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -23282,7 +23344,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -23373,7 +23435,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -23461,7 +23523,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -23525,7 +23587,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -23596,7 +23658,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 232, + "weight": 221, "cookies": false, "type": "", "demo": "migrations\/list.md", @@ -23679,7 +23741,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 226, + "weight": 215, "cookies": false, "type": "", "demo": "migrations\/create-appwrite-migration.md", @@ -23742,7 +23804,8 @@ "type": "string", "description": "Source Appwrite endpoint", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "projectId": { "type": "string", @@ -23792,7 +23855,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 234, + "weight": 223, "cookies": false, "type": "", "demo": "migrations\/get-appwrite-report.md", @@ -23901,7 +23964,7 @@ "x-appwrite": { "method": "createCSVExport", "group": null, - "weight": 231, + "weight": 220, "cookies": false, "type": "", "demo": "migrations\/create-csv-export.md", @@ -24027,7 +24090,7 @@ "x-appwrite": { "method": "createCSVImport", "group": null, - "weight": 230, + "weight": 219, "cookies": false, "type": "", "demo": "migrations\/create-csv-import.md", @@ -24118,7 +24181,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 227, + "weight": 216, "cookies": false, "type": "", "demo": "migrations\/create-firebase-migration.md", @@ -24211,7 +24274,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 235, + "weight": 224, "cookies": false, "type": "", "demo": "migrations\/get-firebase-report.md", @@ -24297,7 +24360,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 229, + "weight": 218, "cookies": false, "type": "", "demo": "migrations\/create-n-host-migration.md", @@ -24391,7 +24454,8 @@ "type": "integer", "description": "Source's Database Port", "default": 5432, - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24432,7 +24496,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 237, + "weight": 226, "cookies": false, "type": "", "demo": "migrations\/get-n-host-report.md", @@ -24568,7 +24632,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 228, + "weight": 217, "cookies": false, "type": "", "demo": "migrations\/create-supabase-migration.md", @@ -24626,7 +24690,8 @@ "type": "string", "description": "Source's Supabase Endpoint", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "apiKey": { "type": "string", @@ -24656,7 +24721,8 @@ "type": "integer", "description": "Source's Database Port", "default": 5432, - "x-example": null + "x-example": null, + "format": "int32" } }, "required": [ @@ -24696,7 +24762,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 236, + "weight": 225, "cookies": false, "type": "", "demo": "migrations\/get-supabase-report.md", @@ -24823,7 +24889,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 233, + "weight": 222, "cookies": false, "type": "", "demo": "migrations\/get.md", @@ -24882,7 +24948,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 238, + "weight": 227, "cookies": false, "type": "", "demo": "migrations\/retry.md", @@ -24936,7 +25002,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 239, + "weight": 228, "cookies": false, "type": "", "demo": "migrations\/delete.md", @@ -24995,7 +25061,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 138, + "weight": 127, "cookies": false, "type": "", "demo": "project\/get-usage.md", @@ -25078,7 +25144,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 140, + "weight": 129, "cookies": false, "type": "", "demo": "project\/list-variables.md", @@ -25127,7 +25193,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 139, + "weight": 128, "cookies": false, "type": "", "demo": "project\/create-variable.md", @@ -25209,7 +25275,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 141, + "weight": 130, "cookies": false, "type": "", "demo": "project\/get-variable.md", @@ -25268,7 +25334,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 142, + "weight": 131, "cookies": false, "type": "", "demo": "project\/update-variable.md", @@ -25354,7 +25420,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 143, + "weight": 132, "cookies": false, "type": "", "demo": "project\/delete-variable.md", @@ -25438,7 +25504,7 @@ "parameters": [ { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search", "required": false, "type": "array", "collectionFormat": "multi", @@ -25493,7 +25559,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 92, + "weight": 81, "cookies": false, "type": "", "demo": "projects\/create.md", @@ -25568,7 +25634,8 @@ "type": "string", "description": "Project URL.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25641,7 +25708,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 93, + "weight": 82, "cookies": false, "type": "", "demo": "projects\/get.md", @@ -25700,7 +25767,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 94, + "weight": 83, "cookies": false, "type": "", "demo": "projects\/update.md", @@ -25760,7 +25827,8 @@ "type": "string", "description": "Project URL.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "legalName": { "type": "string", @@ -25826,7 +25894,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 111, + "weight": 100, "cookies": false, "type": "", "demo": "projects\/delete.md", @@ -25887,7 +25955,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 98, + "weight": 87, "cookies": false, "type": "", "demo": "projects\/update-api-status.md", @@ -26044,7 +26112,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 99, + "weight": 88, "cookies": false, "type": "", "demo": "projects\/update-api-status-all.md", @@ -26183,7 +26251,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 104, + "weight": 93, "cookies": false, "type": "", "demo": "projects\/update-auth-duration.md", @@ -26225,7 +26293,8 @@ "type": "integer", "description": "Project session length in seconds. Max length: 31536000 seconds.", "default": null, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26262,7 +26331,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 103, + "weight": 92, "cookies": false, "type": "", "demo": "projects\/update-auth-limit.md", @@ -26304,7 +26373,8 @@ "type": "integer", "description": "Set the max number of users allowed in this project. Use 0 for unlimited.", "default": null, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26341,7 +26411,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 109, + "weight": 98, "cookies": false, "type": "", "demo": "projects\/update-auth-sessions-limit.md", @@ -26383,7 +26453,8 @@ "type": "integer", "description": "Set the max number of users allowed in this project. Value allowed is between 1-100. Default is 10", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" } }, "required": [ @@ -26420,7 +26491,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 102, + "weight": 91, "cookies": false, "type": "", "demo": "projects\/update-memberships-privacy.md", @@ -26513,7 +26584,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 110, + "weight": 99, "cookies": false, "type": "", "demo": "projects\/update-mock-numbers.md", @@ -26595,7 +26666,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 107, + "weight": 96, "cookies": false, "type": "", "demo": "projects\/update-auth-password-dictionary.md", @@ -26674,7 +26745,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 106, + "weight": 95, "cookies": false, "type": "", "demo": "projects\/update-auth-password-history.md", @@ -26716,7 +26787,8 @@ "type": "integer", "description": "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 is20. Default value is 0", "default": null, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -26753,7 +26825,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 108, + "weight": 97, "cookies": false, "type": "", "demo": "projects\/update-personal-data-check.md", @@ -26832,7 +26904,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 101, + "weight": 90, "cookies": false, "type": "", "demo": "projects\/update-session-alerts.md", @@ -26911,7 +26983,7 @@ "x-appwrite": { "method": "updateSessionInvalidation", "group": "auth", - "weight": 137, + "weight": 126, "cookies": false, "type": "", "demo": "projects\/update-session-invalidation.md", @@ -26990,7 +27062,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 105, + "weight": 94, "cookies": false, "type": "", "demo": "projects\/update-auth-status.md", @@ -27459,7 +27531,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 123, + "weight": 112, "cookies": false, "type": "", "demo": "projects\/create-jwt.md", @@ -27569,7 +27641,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } }, "required": [ @@ -27604,7 +27677,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 119, + "weight": 108, "cookies": false, "type": "", "demo": "projects\/list-keys.md", @@ -27672,7 +27745,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 118, + "weight": 107, "cookies": false, "type": "", "demo": "projects\/create-key.md", @@ -27826,7 +27899,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 120, + "weight": 109, "cookies": false, "type": "", "demo": "projects\/get-key.md", @@ -27893,7 +27966,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 121, + "weight": 110, "cookies": false, "type": "", "demo": "projects\/update-key.md", @@ -28050,7 +28123,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 122, + "weight": 111, "cookies": false, "type": "", "demo": "projects\/delete-key.md", @@ -28200,7 +28273,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 100, + "weight": 89, "cookies": false, "type": "", "demo": "projects\/update-o-auth-2.md", @@ -28343,7 +28416,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 125, + "weight": 114, "cookies": false, "type": "", "demo": "projects\/list-platforms.md", @@ -28411,7 +28484,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 124, + "weight": 113, "cookies": false, "type": "", "demo": "projects\/create-platform.md", @@ -28532,7 +28605,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 126, + "weight": 115, "cookies": false, "type": "", "demo": "projects\/get-platform.md", @@ -28599,7 +28672,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 127, + "weight": 116, "cookies": false, "type": "", "demo": "projects\/update-platform.md", @@ -28697,7 +28770,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 128, + "weight": 117, "cookies": false, "type": "", "demo": "projects\/delete-platform.md", @@ -28766,7 +28839,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 96, + "weight": 85, "cookies": false, "type": "", "demo": "projects\/update-service-status.md", @@ -28869,7 +28942,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 97, + "weight": 86, "cookies": false, "type": "", "demo": "projects\/update-service-status-all.md", @@ -28948,7 +29021,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 129, + "weight": 118, "cookies": false, "type": "", "demo": "projects\/update-smtp.md", @@ -29078,13 +29151,15 @@ "type": "string", "description": "Email of the sender", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -29096,7 +29171,8 @@ "type": "integer", "description": "SMTP server port", "default": 587, - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29154,7 +29230,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 130, + "weight": 119, "cookies": false, "type": "", "demo": "projects\/create-smtp-test.md", @@ -29291,13 +29367,15 @@ "type": "string", "description": "Email of the sender", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "host": { "type": "string", @@ -29309,7 +29387,8 @@ "type": "integer", "description": "SMTP server port", "default": 587, - "x-example": null + "x-example": null, + "format": "int32" }, "username": { "type": "string", @@ -29373,7 +29452,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 95, + "weight": 84, "cookies": false, "type": "", "demo": "projects\/update-team.md", @@ -29450,7 +29529,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 132, + "weight": 121, "cookies": false, "type": "", "demo": "projects\/get-email-template.md", @@ -29671,7 +29750,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 134, + "weight": 123, "cookies": false, "type": "", "demo": "projects\/update-email-template.md", @@ -29893,13 +29972,15 @@ "type": "string", "description": "Email of the sender", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyTo": { "type": "string", "description": "Reply to email", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -29935,7 +30016,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 136, + "weight": 125, "cookies": false, "type": "", "demo": "projects\/delete-email-template.md", @@ -30156,7 +30237,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 131, + "weight": 120, "cookies": false, "type": "", "demo": "projects\/get-sms-template.md", @@ -30438,7 +30519,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 133, + "weight": 122, "cookies": false, "type": "", "demo": "projects\/update-sms-template.md", @@ -30742,7 +30823,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 135, + "weight": 124, "cookies": false, "type": "", "demo": "projects\/delete-sms-template.md", @@ -31024,7 +31105,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 113, + "weight": 102, "cookies": false, "type": "", "demo": "projects\/list-webhooks.md", @@ -31092,7 +31173,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 112, + "weight": 101, "cookies": false, "type": "", "demo": "projects\/create-webhook.md", @@ -31211,7 +31292,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 114, + "weight": 103, "cookies": false, "type": "", "demo": "projects\/get-webhook.md", @@ -31278,7 +31359,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 115, + "weight": 104, "cookies": false, "type": "", "demo": "projects\/update-webhook.md", @@ -31400,7 +31481,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 117, + "weight": 106, "cookies": false, "type": "", "demo": "projects\/delete-webhook.md", @@ -31469,7 +31550,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 116, + "weight": 105, "cookies": false, "type": "", "demo": "projects\/update-webhook-signature.md", @@ -31810,7 +31891,8 @@ "type": "string", "description": "Target URL of redirection", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "statusCode": { "type": "string", @@ -32309,7 +32391,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -32993,7 +33076,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -34915,7 +34999,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -35124,7 +35209,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -36468,7 +36554,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -38188,6 +38275,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -38301,6 +38389,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -38660,6 +38749,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -38667,6 +38757,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -38674,6 +38765,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -38787,6 +38879,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -38794,6 +38887,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -38801,6 +38895,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -38914,6 +39009,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -38921,6 +39017,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -38928,6 +39025,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -39041,6 +39139,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -39048,6 +39147,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -39055,6 +39155,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -40184,7 +40285,8 @@ "type": "integer", "description": "Column size for text columns, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -40324,6 +40426,7 @@ "description": "Maximum size of the string column.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -40437,6 +40540,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -40550,6 +40654,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -42589,13 +42694,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -42709,13 +42816,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -42953,7 +43062,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -43038,7 +43147,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -43129,7 +43238,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -43192,7 +43301,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -43268,7 +43377,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -43331,7 +43440,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 157, + "weight": 146, "cookies": false, "type": "", "demo": "teams\/list-logs.md", @@ -43411,7 +43520,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -43504,7 +43613,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -43550,7 +43659,8 @@ "type": "string", "description": "Email of the new team member.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -43562,7 +43672,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -43584,7 +43695,8 @@ "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -43625,7 +43737,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -43696,7 +43808,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -43790,7 +43902,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -43863,7 +43975,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -43958,7 +44070,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -44020,7 +44132,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -44464,7 +44576,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -44547,7 +44659,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -44590,6 +44702,7 @@ "description": "User email.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { @@ -44597,6 +44710,7 @@ "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -44646,7 +44760,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -44688,13 +44802,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44739,7 +44855,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -44781,13 +44897,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -44830,7 +44948,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -44910,7 +45028,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -44973,7 +45091,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -45015,13 +45133,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45066,7 +45186,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -45108,13 +45228,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -45159,7 +45281,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -45201,13 +45323,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45219,25 +45343,29 @@ "type": "integer", "description": "Optional CPU cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -45287,7 +45415,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -45329,13 +45457,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -45401,7 +45531,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -45443,13 +45573,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -45513,7 +45645,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 189, "cookies": false, "type": "", "demo": "users\/get-usage.md", @@ -45584,7 +45716,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -45640,7 +45772,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -45703,7 +45835,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -45747,7 +45879,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -45784,7 +45917,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -45834,7 +45967,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -45868,7 +46002,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -45950,7 +46084,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -46032,7 +46166,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -46125,7 +46259,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -46261,7 +46395,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -46393,7 +46527,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -46510,7 +46644,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -46627,7 +46761,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -46744,7 +46878,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -46863,7 +46997,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -46944,7 +47078,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -47025,7 +47159,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -47069,7 +47203,8 @@ "type": "string", "description": "User phone number.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -47104,7 +47239,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -47165,7 +47300,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -47244,7 +47379,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -47314,7 +47449,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -47370,7 +47505,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -47428,7 +47563,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -47499,7 +47634,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -47578,7 +47713,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -47660,7 +47795,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -47772,7 +47907,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -47841,7 +47976,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -47932,7 +48067,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -48003,7 +48138,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -48047,13 +48182,15 @@ "type": "integer", "description": "Token length in characters. The default length is 6 characters", "default": 6, - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", "default": 900, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -48087,7 +48224,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -48168,7 +48305,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -48249,7 +48386,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 204, + "weight": 193, "cookies": false, "type": "", "demo": "vcs\/create-repository-detection.md", @@ -48345,7 +48482,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 205, + "weight": 194, "cookies": false, "type": "", "demo": "vcs\/list-repositories.md", @@ -48439,7 +48576,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 206, + "weight": 195, "cookies": false, "type": "", "demo": "vcs\/create-repository.md", @@ -48523,7 +48660,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 207, + "weight": 196, "cookies": false, "type": "", "demo": "vcs\/get-repository.md", @@ -48590,7 +48727,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 208, + "weight": 197, "cookies": false, "type": "", "demo": "vcs\/list-repository-branches.md", @@ -48657,7 +48794,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 203, + "weight": 192, "cookies": false, "type": "", "demo": "vcs\/get-repository-contents.md", @@ -48741,7 +48878,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 213, + "weight": 202, "cookies": false, "type": "", "demo": "vcs\/update-external-deployments.md", @@ -48826,7 +48963,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 210, + "weight": 199, "cookies": false, "type": "", "demo": "vcs\/list-installations.md", @@ -48907,7 +49044,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 211, + "weight": 200, "cookies": false, "type": "", "demo": "vcs\/get-installation.md", @@ -48961,7 +49098,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 212, + "weight": 201, "cookies": false, "type": "", "demo": "vcs\/delete-installation.md", @@ -50939,14 +51076,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { @@ -52389,14 +52526,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 63e43dbf69..284c917919 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -202,7 +202,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", @@ -292,13 +293,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -513,7 +516,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -624,7 +628,7 @@ "x-appwrite": { "method": "updateMFA", "group": "mfa", - "weight": 288, + "weight": 277, "cookies": false, "type": "", "demo": "account\/update-mfa.md", @@ -700,7 +704,7 @@ "x-appwrite": { "method": "createMfaAuthenticator", "group": "mfa", - "weight": 290, + "weight": 279, "cookies": false, "type": "", "demo": "account\/create-mfa-authenticator.md", @@ -827,7 +831,7 @@ "x-appwrite": { "method": "updateMfaAuthenticator", "group": "mfa", - "weight": 291, + "weight": 280, "cookies": false, "type": "", "demo": "account\/update-mfa-authenticator.md", @@ -971,7 +975,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 292, + "weight": 281, "cookies": false, "type": "", "demo": "account\/delete-mfa-authenticator.md", @@ -1098,7 +1102,7 @@ "x-appwrite": { "method": "createMfaChallenge", "group": "mfa", - "weight": 296, + "weight": 285, "cookies": false, "type": "", "demo": "account\/create-mfa-challenge.md", @@ -1238,7 +1242,7 @@ "x-appwrite": { "method": "updateMfaChallenge", "group": "mfa", - "weight": 297, + "weight": 286, "cookies": false, "type": "", "demo": "account\/update-mfa-challenge.md", @@ -1381,7 +1385,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 289, + "weight": 278, "cookies": false, "type": "", "demo": "account\/list-mfa-factors.md", @@ -1485,7 +1489,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 295, + "weight": 284, "cookies": false, "type": "", "demo": "account\/get-mfa-recovery-codes.md", @@ -1589,7 +1593,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 293, + "weight": 282, "cookies": false, "type": "", "demo": "account\/create-mfa-recovery-codes.md", @@ -1693,7 +1697,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 294, + "weight": 283, "cookies": false, "type": "", "demo": "account\/update-mfa-recovery-codes.md", @@ -1920,7 +1924,8 @@ "type": "string", "description": "Current user password. Must be at least 8 chars.", "default": "", - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -1996,13 +2001,15 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -2210,13 +2217,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "URL to redirect the user back to your app from the recovery 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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -2540,13 +2549,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password. Must be at least 8 chars.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" } }, "required": [ @@ -3132,7 +3143,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "phrase": { "type": "boolean", @@ -3224,13 +3236,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "url": { "type": "string", "description": "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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "phrase": { "type": "boolean", @@ -3460,7 +3474,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -3591,7 +3606,8 @@ "type": "string", "description": "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.", "default": null, - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" } }, "required": [ @@ -3905,7 +3921,7 @@ "x-appwrite": { "method": "getBrowser", "group": null, - "weight": 50, + "weight": 288, "cookies": false, "type": "location", "demo": "avatars\/get-browser.md", @@ -4033,7 +4049,7 @@ "x-appwrite": { "method": "getCreditCard", "group": null, - "weight": 49, + "weight": 287, "cookies": false, "type": "location", "demo": "avatars\/get-credit-card.md", @@ -4167,7 +4183,7 @@ "x-appwrite": { "method": "getFavicon", "group": null, - "weight": 53, + "weight": 291, "cookies": false, "type": "location", "demo": "avatars\/get-favicon.md", @@ -4233,7 +4249,7 @@ "x-appwrite": { "method": "getFlag", "group": null, - "weight": 51, + "weight": 289, "cookies": false, "type": "location", "demo": "avatars\/get-flag.md", @@ -4723,7 +4739,7 @@ "x-appwrite": { "method": "getImage", "group": null, - "weight": 52, + "weight": 290, "cookies": false, "type": "location", "demo": "avatars\/get-image.md", @@ -4809,7 +4825,7 @@ "x-appwrite": { "method": "getInitials", "group": null, - "weight": 55, + "weight": 293, "cookies": false, "type": "location", "demo": "avatars\/get-initials.md", @@ -4903,7 +4919,7 @@ "x-appwrite": { "method": "getQR", "group": null, - "weight": 54, + "weight": 292, "cookies": false, "type": "location", "demo": "avatars\/get-qr.md", @@ -4997,7 +5013,7 @@ "x-appwrite": { "method": "getScreenshot", "group": null, - "weight": 56, + "weight": 294, "cookies": false, "type": "location", "demo": "avatars\/get-screenshot.md", @@ -6061,7 +6077,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -7809,6 +7826,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -7924,6 +7942,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -8289,6 +8308,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8296,6 +8316,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8303,6 +8324,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -8418,6 +8440,7 @@ "description": "Minimum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -8425,6 +8448,7 @@ "description": "Maximum value.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -8432,6 +8456,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -8547,6 +8572,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -8554,6 +8580,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -8561,6 +8588,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -8676,6 +8704,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -8683,6 +8712,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -8690,6 +8720,7 @@ "description": "Default value. Cannot be set when attribute is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -9839,7 +9870,8 @@ "type": "integer", "description": "Attribute size for text attributes, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -9981,6 +10013,7 @@ "description": "Maximum size of the string attribute.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -10096,6 +10129,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -10211,6 +10245,7 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -11746,13 +11781,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -11869,13 +11906,15 @@ "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -12540,7 +12579,8 @@ "type": "integer", "description": "Function maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -13019,7 +13059,8 @@ "type": "integer", "description": "Maximum execution time in seconds.", "default": 15, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "enabled": { "type": "boolean", @@ -14832,7 +14873,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 225, + "weight": 214, "cookies": false, "type": "graphql", "demo": "graphql\/query.md", @@ -14909,7 +14950,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 224, + "weight": 213, "cookies": false, "type": "graphql", "demo": "graphql\/mutation.md", @@ -14984,7 +15025,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 68, + "weight": 57, "cookies": false, "type": "", "demo": "health\/get.md", @@ -15036,7 +15077,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 89, + "weight": 78, "cookies": false, "type": "", "demo": "health\/get-antivirus.md", @@ -15088,7 +15129,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 71, + "weight": 60, "cookies": false, "type": "", "demo": "health\/get-cache.md", @@ -15140,7 +15181,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 76, + "weight": 65, "cookies": false, "type": "", "demo": "health\/get-certificate.md", @@ -15201,7 +15242,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 70, + "weight": 59, "cookies": false, "type": "", "demo": "health\/get-db.md", @@ -15253,7 +15294,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 72, + "weight": 61, "cookies": false, "type": "", "demo": "health\/get-pub-sub.md", @@ -15305,7 +15346,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 78, + "weight": 67, "cookies": false, "type": "", "demo": "health\/get-queue-builds.md", @@ -15368,7 +15409,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 77, + "weight": 66, "cookies": false, "type": "", "demo": "health\/get-queue-certificates.md", @@ -15431,7 +15472,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 79, + "weight": 68, "cookies": false, "type": "", "demo": "health\/get-queue-databases.md", @@ -15503,7 +15544,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 80, + "weight": 69, "cookies": false, "type": "", "demo": "health\/get-queue-deletes.md", @@ -15566,7 +15607,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 90, + "weight": 79, "cookies": false, "type": "", "demo": "health\/get-failed-jobs.md", @@ -15610,6 +15651,7 @@ "v1-webhooks", "v1-certificates", "v1-builds", + "v1-screenshots", "v1-messaging", "v1-migrations" ], @@ -15653,7 +15695,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 84, + "weight": 73, "cookies": false, "type": "", "demo": "health\/get-queue-functions.md", @@ -15716,7 +15758,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 75, + "weight": 64, "cookies": false, "type": "", "demo": "health\/get-queue-logs.md", @@ -15779,7 +15821,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 81, + "weight": 70, "cookies": false, "type": "", "demo": "health\/get-queue-mails.md", @@ -15842,7 +15884,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 82, + "weight": 71, "cookies": false, "type": "", "demo": "health\/get-queue-messaging.md", @@ -15905,7 +15947,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 83, + "weight": 72, "cookies": false, "type": "", "demo": "health\/get-queue-migrations.md", @@ -15968,7 +16010,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 85, + "weight": 74, "cookies": false, "type": "", "demo": "health\/get-queue-stats-resources.md", @@ -16031,7 +16073,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 86, + "weight": 75, "cookies": false, "type": "", "demo": "health\/get-queue-usage.md", @@ -16094,7 +16136,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 74, + "weight": 63, "cookies": false, "type": "", "demo": "health\/get-queue-webhooks.md", @@ -16157,7 +16199,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 88, + "weight": 77, "cookies": false, "type": "", "demo": "health\/get-storage.md", @@ -16209,7 +16251,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 87, + "weight": 76, "cookies": false, "type": "", "demo": "health\/get-storage-local.md", @@ -16261,7 +16303,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 73, + "weight": 62, "cookies": false, "type": "", "demo": "health\/get-time.md", @@ -16313,7 +16355,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 60, + "weight": 49, "cookies": false, "type": "", "demo": "locale\/get.md", @@ -16368,7 +16410,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 61, + "weight": 50, "cookies": false, "type": "", "demo": "locale\/list-codes.md", @@ -16423,7 +16465,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 65, + "weight": 54, "cookies": false, "type": "", "demo": "locale\/list-continents.md", @@ -16478,7 +16520,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 62, + "weight": 51, "cookies": false, "type": "", "demo": "locale\/list-countries.md", @@ -16533,7 +16575,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 63, + "weight": 52, "cookies": false, "type": "", "demo": "locale\/list-countries-eu.md", @@ -16588,7 +16630,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 64, + "weight": 53, "cookies": false, "type": "", "demo": "locale\/list-countries-phones.md", @@ -16643,7 +16685,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 66, + "weight": 55, "cookies": false, "type": "", "demo": "locale\/list-currencies.md", @@ -16698,7 +16740,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 67, + "weight": 56, "cookies": false, "type": "", "demo": "locale\/list-languages.md", @@ -16753,7 +16795,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 280, + "weight": 269, "cookies": false, "type": "", "demo": "messaging\/list-messages.md", @@ -16839,7 +16881,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 277, + "weight": 266, "cookies": false, "type": "", "demo": "messaging\/create-email.md", @@ -17000,7 +17042,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 284, + "weight": 273, "cookies": false, "type": "", "demo": "messaging\/update-email.md", @@ -17168,7 +17210,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 279, + "weight": 268, "cookies": false, "type": "", "demo": "messaging\/create-push.md", @@ -17293,7 +17335,8 @@ "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", "default": -1, - "x-example": null + "x-example": null, + "format": "int32" }, "draft": { "type": "boolean", @@ -17367,7 +17410,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 286, + "weight": 275, "cookies": false, "type": "", "demo": "messaging\/update-push.md", @@ -17506,6 +17549,7 @@ "description": "Badge for push notification. Available only for iOS platforms.", "default": null, "x-example": null, + "format": "int32", "x-nullable": true }, "draft": { @@ -17581,7 +17625,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 278, + "weight": 267, "cookies": false, "type": "", "demo": "messaging\/create-sms.md", @@ -17774,7 +17818,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 285, + "weight": 274, "cookies": false, "type": "", "demo": "messaging\/update-sms.md", @@ -17966,7 +18010,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 283, + "weight": 272, "cookies": false, "type": "", "demo": "messaging\/get-message.md", @@ -18023,7 +18067,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 287, + "weight": 276, "cookies": false, "type": "", "demo": "messaging\/delete.md", @@ -18085,7 +18129,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 281, + "weight": 270, "cookies": false, "type": "", "demo": "messaging\/list-message-logs.md", @@ -18168,7 +18212,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 282, + "weight": 271, "cookies": false, "type": "", "demo": "messaging\/list-targets.md", @@ -18251,7 +18295,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 251, + "weight": 240, "cookies": false, "type": "", "demo": "messaging\/list-providers.md", @@ -18337,7 +18381,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 250, + "weight": 239, "cookies": false, "type": "", "demo": "messaging\/create-apns-provider.md", @@ -18529,7 +18573,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 264, + "weight": 253, "cookies": false, "type": "", "demo": "messaging\/update-apns-provider.md", @@ -18718,7 +18762,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 249, + "weight": 238, "cookies": false, "type": "", "demo": "messaging\/create-fcm-provider.md", @@ -18879,7 +18923,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 263, + "weight": 252, "cookies": false, "type": "", "demo": "messaging\/update-fcm-provider.md", @@ -19036,7 +19080,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 240, + "weight": 229, "cookies": false, "type": "", "demo": "messaging\/create-mailgun-provider.md", @@ -19110,7 +19154,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19122,7 +19167,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19167,7 +19213,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 254, + "weight": 243, "cookies": false, "type": "", "demo": "messaging\/update-mailgun-provider.md", @@ -19250,7 +19296,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19296,7 +19343,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 244, + "weight": 233, "cookies": false, "type": "", "demo": "messaging\/create-msg-91-provider.md", @@ -19402,7 +19449,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 258, + "weight": 247, "cookies": false, "type": "", "demo": "messaging\/update-msg-91-provider.md", @@ -19506,7 +19553,7 @@ "x-appwrite": { "method": "createResendProvider", "group": "providers", - "weight": 242, + "weight": 231, "cookies": false, "type": "", "demo": "messaging\/create-resend-provider.md", @@ -19567,7 +19614,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19579,7 +19627,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19624,7 +19673,7 @@ "x-appwrite": { "method": "updateResendProvider", "group": "providers", - "weight": 256, + "weight": 245, "cookies": false, "type": "", "demo": "messaging\/update-resend-provider.md", @@ -19694,7 +19743,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19740,7 +19790,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 241, + "weight": 230, "cookies": false, "type": "", "demo": "messaging\/create-sendgrid-provider.md", @@ -19801,7 +19851,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19813,7 +19864,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -19858,7 +19910,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 255, + "weight": 244, "cookies": false, "type": "", "demo": "messaging\/update-sendgrid-provider.md", @@ -19928,7 +19980,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -19974,7 +20027,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 243, + "weight": 232, "cookies": false, "type": "", "demo": "messaging\/create-smtp-provider.md", @@ -20117,7 +20170,8 @@ "type": "integer", "description": "The default SMTP server port.", "default": 587, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "username": { "type": "string", @@ -20166,7 +20220,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20178,7 +20233,8 @@ "type": "string", "description": "Email set in the reply to field for the mail. Default value is sender email.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "enabled": { "type": "boolean", @@ -20224,7 +20280,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 257, + "weight": 246, "cookies": false, "type": "", "demo": "messaging\/update-smtp-provider.md", @@ -20366,6 +20422,7 @@ "description": "SMTP port.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "username": { @@ -20416,7 +20473,8 @@ "type": "string", "description": "Sender email address.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "replyToName": { "type": "string", @@ -20469,7 +20527,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 245, + "weight": 234, "cookies": false, "type": "", "demo": "messaging\/create-telesign-provider.md", @@ -20518,7 +20576,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "customerId": { "type": "string", @@ -20575,7 +20634,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 259, + "weight": 248, "cookies": false, "type": "", "demo": "messaging\/update-telesign-provider.md", @@ -20679,7 +20738,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 246, + "weight": 235, "cookies": false, "type": "", "demo": "messaging\/create-textmagic-provider.md", @@ -20728,7 +20787,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "username": { "type": "string", @@ -20785,7 +20845,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 260, + "weight": 249, "cookies": false, "type": "", "demo": "messaging\/update-textmagic-provider.md", @@ -20889,7 +20949,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 247, + "weight": 236, "cookies": false, "type": "", "demo": "messaging\/create-twilio-provider.md", @@ -20938,7 +20998,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "accountSid": { "type": "string", @@ -20995,7 +21056,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 261, + "weight": 250, "cookies": false, "type": "", "demo": "messaging\/update-twilio-provider.md", @@ -21099,7 +21160,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 248, + "weight": 237, "cookies": false, "type": "", "demo": "messaging\/create-vonage-provider.md", @@ -21148,7 +21209,8 @@ "type": "string", "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "apiKey": { "type": "string", @@ -21205,7 +21267,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 262, + "weight": 251, "cookies": false, "type": "", "demo": "messaging\/update-vonage-provider.md", @@ -21307,7 +21369,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 253, + "weight": 242, "cookies": false, "type": "", "demo": "messaging\/get-provider.md", @@ -21364,7 +21426,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 265, + "weight": 254, "cookies": false, "type": "", "demo": "messaging\/delete-provider.md", @@ -21426,7 +21488,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 252, + "weight": 241, "cookies": false, "type": "", "demo": "messaging\/list-provider-logs.md", @@ -21509,7 +21571,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 274, + "weight": 263, "cookies": false, "type": "", "demo": "messaging\/list-subscriber-logs.md", @@ -21592,7 +21654,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 267, + "weight": 256, "cookies": false, "type": "", "demo": "messaging\/list-topics.md", @@ -21676,7 +21738,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 266, + "weight": 255, "cookies": false, "type": "", "demo": "messaging\/create-topic.md", @@ -21766,7 +21828,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 269, + "weight": 258, "cookies": false, "type": "", "demo": "messaging\/get-topic.md", @@ -21828,7 +21890,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 270, + "weight": 259, "cookies": false, "type": "", "demo": "messaging\/update-topic.md", @@ -21911,7 +21973,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 271, + "weight": 260, "cookies": false, "type": "", "demo": "messaging\/delete-topic.md", @@ -21973,7 +22035,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 268, + "weight": 257, "cookies": false, "type": "", "demo": "messaging\/list-topic-logs.md", @@ -22056,7 +22118,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 273, + "weight": 262, "cookies": false, "type": "", "demo": "messaging\/list-subscribers.md", @@ -22148,7 +22210,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 272, + "weight": 261, "cookies": false, "type": "", "demo": "messaging\/create-subscriber.md", @@ -22238,7 +22300,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 275, + "weight": 264, "cookies": false, "type": "", "demo": "messaging\/get-subscriber.md", @@ -22303,7 +22365,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 276, + "weight": 265, "cookies": false, "type": "", "demo": "messaging\/delete-subscriber.md", @@ -22544,7 +22606,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -22981,7 +23044,8 @@ "type": "integer", "description": "Maximum request time in seconds.", "default": 30, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "installCommand": { "type": "string", @@ -24846,7 +24910,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -25057,7 +25122,8 @@ "type": "integer", "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", "default": {}, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "allowedFileExtensions": { "type": "array", @@ -26274,7 +26340,8 @@ "type": "integer", "description": "Seconds before the transaction expires.", "default": 300, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -27919,6 +27986,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "array": { @@ -28033,6 +28101,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "newKey": { @@ -28395,6 +28464,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -28402,6 +28472,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -28409,6 +28480,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "array": { @@ -28523,6 +28595,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "max": { @@ -28530,6 +28603,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "default": { @@ -28537,6 +28611,7 @@ "description": "Default value. Cannot be set when required.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "newKey": { @@ -28651,6 +28726,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -28658,6 +28734,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -28665,6 +28742,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "array": { @@ -28779,6 +28857,7 @@ "description": "Minimum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "max": { @@ -28786,6 +28865,7 @@ "description": "Maximum value", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "default": { @@ -28793,6 +28873,7 @@ "description": "Default value. Cannot be set when column is required.", "default": null, "x-example": null, + "format": "int64", "x-nullable": true }, "newKey": { @@ -29932,7 +30013,8 @@ "type": "integer", "description": "Column size for text columns, in number of characters.", "default": null, - "x-example": 1 + "x-example": 1, + "format": "int32" }, "required": { "type": "boolean", @@ -30073,6 +30155,7 @@ "description": "Maximum size of the string column.", "default": null, "x-example": 1, + "format": "int32", "x-nullable": true }, "newKey": { @@ -30187,6 +30270,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "array": { @@ -30301,6 +30385,7 @@ "description": "Default value for column when not provided. Cannot be set when column is required.", "default": null, "x-example": "https:\/\/example.com", + "format": "url", "x-nullable": true }, "newKey": { @@ -32196,13 +32281,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "min": { "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32318,13 +32405,15 @@ "type": "number", "description": "Value to increment the column by. The value must be a number.", "default": 1, - "x-example": null + "x-example": null, + "format": "float" }, "max": { "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null, + "format": "float", "x-nullable": true }, "transactionId": { @@ -32364,7 +32453,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 145, + "weight": 134, "cookies": false, "type": "", "demo": "teams\/list.md", @@ -32451,7 +32540,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 144, + "weight": 133, "cookies": false, "type": "", "demo": "teams\/create.md", @@ -32544,7 +32633,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 146, + "weight": 135, "cookies": false, "type": "", "demo": "teams\/get.md", @@ -32609,7 +32698,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 148, + "weight": 137, "cookies": false, "type": "", "demo": "teams\/update-name.md", @@ -32687,7 +32776,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 150, + "weight": 139, "cookies": false, "type": "", "demo": "teams\/delete.md", @@ -32752,7 +32841,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 152, + "weight": 141, "cookies": false, "type": "", "demo": "teams\/list-memberships.md", @@ -32847,7 +32936,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 151, + "weight": 140, "cookies": false, "type": "", "demo": "teams\/create-membership.md", @@ -32895,7 +32984,8 @@ "type": "string", "description": "Email of the new team member.", "default": "", - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "userId": { "type": "string", @@ -32907,7 +32997,8 @@ "type": "string", "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": "", - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" }, "roles": { "type": "array", @@ -32929,7 +33020,8 @@ "type": "string", "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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.", "default": "", - "x-example": "https:\/\/example.com" + "x-example": "https:\/\/example.com", + "format": "url" }, "name": { "type": "string", @@ -32970,7 +33062,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 153, + "weight": 142, "cookies": false, "type": "", "demo": "teams\/get-membership.md", @@ -33043,7 +33135,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 154, + "weight": 143, "cookies": false, "type": "", "demo": "teams\/update-membership.md", @@ -33139,7 +33231,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 156, + "weight": 145, "cookies": false, "type": "", "demo": "teams\/delete-membership.md", @@ -33214,7 +33306,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 155, + "weight": 144, "cookies": false, "type": "", "demo": "teams\/update-membership-status.md", @@ -33311,7 +33403,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 147, + "weight": 136, "cookies": false, "type": "", "demo": "teams\/get-prefs.md", @@ -33375,7 +33467,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 149, + "weight": 138, "cookies": false, "type": "", "demo": "teams\/update-prefs.md", @@ -33826,7 +33918,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 167, + "weight": 156, "cookies": false, "type": "", "demo": "users\/list.md", @@ -33910,7 +34002,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 158, + "weight": 147, "cookies": false, "type": "", "demo": "users\/create.md", @@ -33954,6 +34046,7 @@ "description": "User email.", "default": null, "x-example": "email@example.com", + "format": "email", "x-nullable": true }, "phone": { @@ -33961,6 +34054,7 @@ "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", "default": null, "x-example": "+12065550100", + "format": "phone", "x-nullable": true }, "password": { @@ -34010,7 +34104,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 161, + "weight": 150, "cookies": false, "type": "", "demo": "users\/create-argon-2-user.md", @@ -34053,13 +34147,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Argon2.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34104,7 +34200,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 159, + "weight": 148, "cookies": false, "type": "", "demo": "users\/create-bcrypt-user.md", @@ -34147,13 +34243,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Bcrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34196,7 +34294,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 175, + "weight": 164, "cookies": false, "type": "", "demo": "users\/list-identities.md", @@ -34277,7 +34375,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 198, + "weight": 187, "cookies": false, "type": "", "demo": "users\/delete-identity.md", @@ -34341,7 +34439,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 160, + "weight": 149, "cookies": false, "type": "", "demo": "users\/create-md-5-user.md", @@ -34384,13 +34482,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using MD5.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34435,7 +34535,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 163, + "weight": 152, "cookies": false, "type": "", "demo": "users\/create-ph-pass-user.md", @@ -34478,13 +34578,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using PHPass.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "name": { "type": "string", @@ -34529,7 +34631,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 164, + "weight": 153, "cookies": false, "type": "", "demo": "users\/create-scrypt-user.md", @@ -34572,13 +34674,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34590,25 +34694,29 @@ "type": "integer", "description": "Optional CPU cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordMemory": { "type": "integer", "description": "Optional memory cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordParallel": { "type": "integer", "description": "Optional parallelization cost used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "passwordLength": { "type": "integer", "description": "Optional hash length used to hash password.", "default": null, - "x-example": null + "x-example": null, + "format": "int32" }, "name": { "type": "string", @@ -34658,7 +34766,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 165, + "weight": 154, "cookies": false, "type": "", "demo": "users\/create-scrypt-modified-user.md", @@ -34701,13 +34809,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using Scrypt Modified.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordSalt": { "type": "string", @@ -34773,7 +34883,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 162, + "weight": 151, "cookies": false, "type": "", "demo": "users\/create-sha-user.md", @@ -34816,13 +34926,15 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" }, "password": { "type": "string", "description": "User password hashed using SHA.", "default": null, - "x-example": "password" + "x-example": "password", + "format": "password" }, "passwordVersion": { "type": "string", @@ -34886,7 +34998,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 168, + "weight": 157, "cookies": false, "type": "", "demo": "users\/get.md", @@ -34943,7 +35055,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 196, + "weight": 185, "cookies": false, "type": "", "demo": "users\/delete.md", @@ -35007,7 +35119,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 181, + "weight": 170, "cookies": false, "type": "", "demo": "users\/update-email.md", @@ -35052,7 +35164,8 @@ "type": "string", "description": "User email.", "default": null, - "x-example": "email@example.com" + "x-example": "email@example.com", + "format": "email" } }, "required": [ @@ -35089,7 +35202,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 199, + "weight": 188, "cookies": false, "type": "", "demo": "users\/create-jwt.md", @@ -35140,7 +35253,8 @@ "type": "integer", "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", "default": 900, - "x-example": 0 + "x-example": 0, + "format": "int32" } } } @@ -35174,7 +35288,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 177, + "weight": 166, "cookies": false, "type": "", "demo": "users\/update-labels.md", @@ -35257,7 +35371,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 173, + "weight": 162, "cookies": false, "type": "", "demo": "users\/list-logs.md", @@ -35340,7 +35454,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 172, + "weight": 161, "cookies": false, "type": "", "demo": "users\/list-memberships.md", @@ -35434,7 +35548,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 186, + "weight": 175, "cookies": false, "type": "", "demo": "users\/update-mfa.md", @@ -35573,7 +35687,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 191, + "weight": 180, "cookies": false, "type": "", "demo": "users\/delete-mfa-authenticator.md", @@ -35708,7 +35822,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 187, + "weight": 176, "cookies": false, "type": "", "demo": "users\/list-mfa-factors.md", @@ -35828,7 +35942,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 188, + "weight": 177, "cookies": false, "type": "", "demo": "users\/get-mfa-recovery-codes.md", @@ -35948,7 +36062,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 190, + "weight": 179, "cookies": false, "type": "", "demo": "users\/update-mfa-recovery-codes.md", @@ -36068,7 +36182,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 189, + "weight": 178, "cookies": false, "type": "", "demo": "users\/create-mfa-recovery-codes.md", @@ -36190,7 +36304,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 179, + "weight": 168, "cookies": false, "type": "", "demo": "users\/update-name.md", @@ -36272,7 +36386,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 180, + "weight": 169, "cookies": false, "type": "", "demo": "users\/update-password.md", @@ -36354,7 +36468,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 182, + "weight": 171, "cookies": false, "type": "", "demo": "users\/update-phone.md", @@ -36399,7 +36513,8 @@ "type": "string", "description": "User phone number.", "default": null, - "x-example": "+12065550100" + "x-example": "+12065550100", + "format": "phone" } }, "required": [ @@ -36434,7 +36549,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 169, + "weight": 158, "cookies": false, "type": "", "demo": "users\/get-prefs.md", @@ -36496,7 +36611,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 184, + "weight": 173, "cookies": false, "type": "", "demo": "users\/update-prefs.md", @@ -36576,7 +36691,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 171, + "weight": 160, "cookies": false, "type": "", "demo": "users\/list-sessions.md", @@ -36647,7 +36762,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 192, + "weight": 181, "cookies": false, "type": "", "demo": "users\/create-session.md", @@ -36704,7 +36819,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 195, + "weight": 184, "cookies": false, "type": "", "demo": "users\/delete-sessions.md", @@ -36763,7 +36878,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 194, + "weight": 183, "cookies": false, "type": "", "demo": "users\/delete-session.md", @@ -36835,7 +36950,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 176, + "weight": 165, "cookies": false, "type": "", "demo": "users\/update-status.md", @@ -36915,7 +37030,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 174, + "weight": 163, "cookies": false, "type": "", "demo": "users\/list-targets.md", @@ -36998,7 +37113,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 166, + "weight": 155, "cookies": false, "type": "", "demo": "users\/create-target.md", @@ -37111,7 +37226,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 170, + "weight": 159, "cookies": false, "type": "", "demo": "users\/get-target.md", @@ -37181,7 +37296,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 185, + "weight": 174, "cookies": false, "type": "", "demo": "users\/update-target.md", @@ -37273,7 +37388,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 197, + "weight": 186, "cookies": false, "type": "", "demo": "users\/delete-target.md", @@ -37345,7 +37460,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 193, + "weight": 182, "cookies": false, "type": "", "demo": "users\/create-token.md", @@ -37390,13 +37505,15 @@ "type": "integer", "description": "Token length in characters. The default length is 6 characters", "default": 6, - "x-example": 4 + "x-example": 4, + "format": "int32" }, "expire": { "type": "integer", "description": "Token expiration period in seconds. The default expiration is 15 minutes.", "default": 900, - "x-example": 60 + "x-example": 60, + "format": "int32" } } } @@ -37430,7 +37547,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 183, + "weight": 172, "cookies": false, "type": "", "demo": "users\/update-email-verification.md", @@ -37512,7 +37629,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 178, + "weight": 167, "cookies": false, "type": "", "demo": "users\/update-phone-verification.md", @@ -39105,14 +39222,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { @@ -40555,14 +40672,14 @@ "type": "integer", "description": "Minimum value to enforce for new documents.", "x-example": 1, - "format": "int32", + "format": "int64", "x-nullable": true }, "max": { "type": "integer", "description": "Maximum value to enforce for new documents.", "x-example": 10, - "format": "int32", + "format": "int64", "x-nullable": true }, "default": { diff --git a/composer.lock b/composer.lock index 8b68b2a1ba..d0765310b2 100644 --- a/composer.lock +++ b/composer.lock @@ -3552,23 +3552,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "27d66630f528473cb563bbcf362d7d9a711b384e" + "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/27d66630f528473cb563bbcf362d7d9a711b384e", - "reference": "27d66630f528473cb563bbcf362d7d9a711b384e", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/662244bd170bab3ba45fd4470ac2e5a36c980131", + "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131", "shasum": "" }, "require": { "php": ">=8.0", "utopia-php/database": "4.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3595,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.2" + "source": "https://github.com/utopia-php/audit/tree/2.0.3" }, - "time": "2026-01-07T07:01:25+00:00" + "time": "2026-01-13T09:49:40+00:00" }, { "name": "utopia-php/auth", @@ -4266,23 +4266,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.36", + "version": "0.33.37", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" + "reference": "30a119d76531d89da9240496940c84fcd9e1758b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", + "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", + "reference": "30a119d76531d89da9240496940c84fcd9e1758b", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4308,9 +4308,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.36" + "source": "https://github.com/utopia-php/http/tree/0.33.37" }, - "time": "2026-01-12T07:32:29+00:00" + "time": "2026-01-13T10:10:21+00:00" }, { "name": "utopia-php/image", @@ -4515,16 +4515,16 @@ }, { "name": "utopia-php/migration", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2" + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/4cb7a0e65a36058d153ef5643090414c6525e4a2", - "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", "shasum": "" }, "require": { @@ -4564,9 +4564,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.4.2" + "source": "https://github.com/utopia-php/migration/tree/1.4.3" }, - "time": "2026-01-08T04:46:18+00:00" + "time": "2026-01-13T09:51:08+00:00" }, { "name": "utopia-php/mongo", @@ -5013,22 +5013,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.6", + "version": "0.8.4", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.36" + "utopia-php/framework": "0.33.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5058,9 +5058,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.6" + "source": "https://github.com/utopia-php/swoole/tree/0.8.4" }, - "time": "2026-01-12T07:57:35+00:00" + "time": "2025-09-07T09:39:46+00:00" }, { "name": "utopia-php/system", @@ -5170,16 +5170,16 @@ }, { "name": "utopia-php/validators", - "version": "0.1.0", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", "shasum": "" }, "require": { @@ -5187,7 +5187,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", + "phpstan/phpstan": "2.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5209,9 +5209,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.1.0" + "source": "https://github.com/utopia-php/validators/tree/0.2.0" }, - "time": "2025-11-18T11:05:46+00:00" + "time": "2026-01-13T09:16:51+00:00" }, { "name": "utopia-php/vcs", @@ -8968,5 +8968,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 58ded9b78a..0989bb2904 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -67,9 +67,9 @@ class Create extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->param('key', '', new Key(), 'Attribute Key.') ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('min', null, new Nullable(new Integer()), 'Minimum value', true) - ->param('max', null, new Nullable(new Integer()), 'Maximum value', true) - ->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when attribute is required.', true) + ->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true) + ->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true) + ->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when attribute is required.', true) ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 84a43018d1..57797d3e03 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -65,9 +65,9 @@ class Update extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->param('key', '', new Key(), 'Attribute Key.') ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('min', null, new Nullable(new Integer()), 'Minimum value', true) - ->param('max', null, new Nullable(new Integer()), 'Maximum value', true) - ->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when attribute is required.') + ->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true) + ->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true) + ->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when attribute is required.') ->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index 45e0cc6f60..f590e8bdbb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -55,9 +55,9 @@ class Create extends IntegerCreate ->param('tableId', '', new UID(), 'Table ID.') ->param('key', '', new Key(), 'Column Key.') ->param('required', null, new Boolean(), 'Is column required?') - ->param('min', null, new Nullable(new Integer()), 'Minimum value', true) - ->param('max', null, new Nullable(new Integer()), 'Maximum value', true) - ->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when column is required.', true) + ->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true) + ->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true) + ->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when column is required.', true) ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index f1f4ebb4a9..83b6f1bfc6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -57,9 +57,9 @@ class Update extends IntegerUpdate ->param('tableId', '', new UID(), 'Table ID.') ->param('key', '', new Key(), 'Column Key.') ->param('required', null, new Boolean(), 'Is column required?') - ->param('min', null, new Nullable(new Integer()), 'Minimum value', true) - ->param('max', null, new Nullable(new Integer()), 'Maximum value', true) - ->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when column is required.') + ->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true) + ->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true) + ->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when column is required.') ->param('newKey', null, new Nullable(new Key()), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 00e98afb60..0be3240ed7 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -550,7 +550,7 @@ class OpenAPI3 extends Format break; case 'Utopia\Validator\Integer': $node['schema']['type'] = $validator->getType(); - $node['schema']['format'] = 'int32'; + $node['schema']['format'] = $validator->getFormat(); if (!empty($param['example'])) { $node['schema']['x-example'] = $param['example']; } @@ -600,7 +600,7 @@ class OpenAPI3 extends Format $node['schema']['items']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); } if ($validator->getType() === 'integer') { - $node['schema']['items']['format'] = 'int32'; + $node['schema']['items']['format'] = $validator->getFormat() ?? 'int32'; } } else { $node['schema']['type'] = $validator->getType(); @@ -625,7 +625,7 @@ class OpenAPI3 extends Format $node['schema']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); } if ($validator->getType() === 'integer') { - $node['format'] = 'int32'; + $node['schema']['format'] = $validator->getFormat() ?? 'int32'; } } break; @@ -694,6 +694,10 @@ class OpenAPI3 extends Format 'x-example' => $node['schema']['x-example'] ?? null ]; + if (isset($node['schema']['format'])) { + $body['content'][$consumes[0]]['schema']['properties'][$name]['format'] = $node['schema']['format']; + } + if (isset($node['schema']['enum'])) { /// If the enum flag is Set, add the enum values to the body $body['content'][$consumes[0]]['schema']['properties'][$name]['enum'] = $node['schema']['enum']; @@ -795,7 +799,7 @@ class OpenAPI3 extends Format case 'integer': $type = 'integer'; - $format = 'int32'; + $format = $rule['format'] ?? 'int32'; break; case 'float': diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 37173c51c6..fe663c6f55 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -539,7 +539,7 @@ class Swagger2 extends Format break; case 'Utopia\Validator\Integer': $node['type'] = $validator->getType(); - $node['format'] = 'int32'; + $node['format'] = $validator->getFormat(); if (!empty($param['example'])) { $node['x-example'] = $param['example']; } @@ -585,7 +585,7 @@ class Swagger2 extends Format $node['items']['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); } if ($validator->getType() === 'integer') { - $node['items']['format'] = 'int32'; + $node['items']['format'] = $validator->getFormat() ?? 'int32'; } } else { $node['type'] = $validator->getType(); @@ -605,7 +605,7 @@ class Swagger2 extends Format $node['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); } if ($validator->getType() === 'integer') { - $node['format'] = 'int32'; + $node['format'] = $validator->getFormat() ?? 'int32'; } } break; @@ -683,6 +683,10 @@ class Swagger2 extends Format 'x-example' => $node['x-example'] ?? null, ]; + if (isset($node['format'])) { + $body['schema']['properties'][$name]['format'] = $node['format']; + } + if (isset($node['enum'])) { /// If the enum flag is Set, add the enum values to the body $body['schema']['properties'][$name]['enum'] = $node['enum']; @@ -776,7 +780,7 @@ class Swagger2 extends Format case 'integer': $type = 'integer'; - $format = 'int32'; + $format = $rule['format'] ?? 'int32'; break; case 'float': diff --git a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php index fddfe57445..ecdfd38e2d 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php @@ -25,6 +25,7 @@ class AttributeInteger extends Attribute ]) ->addRule('min', [ 'type' => self::TYPE_INTEGER, + 'format' => 'int64', 'description' => 'Minimum value to enforce for new documents.', 'default' => null, 'required' => false, @@ -32,6 +33,7 @@ class AttributeInteger extends Attribute ]) ->addRule('max', [ 'type' => self::TYPE_INTEGER, + 'format' => 'int64', 'description' => 'Maximum value to enforce for new documents.', 'default' => null, 'required' => false, diff --git a/src/Appwrite/Utopia/Response/Model/ColumnInteger.php b/src/Appwrite/Utopia/Response/Model/ColumnInteger.php index 9f6c2c89ab..b248a8d88e 100644 --- a/src/Appwrite/Utopia/Response/Model/ColumnInteger.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnInteger.php @@ -25,6 +25,7 @@ class ColumnInteger extends Column ]) ->addRule('min', [ 'type' => self::TYPE_INTEGER, + 'format' => 'int64', 'description' => 'Minimum value to enforce for new documents.', 'default' => null, 'required' => false, @@ -32,6 +33,7 @@ class ColumnInteger extends Column ]) ->addRule('max', [ 'type' => self::TYPE_INTEGER, + 'format' => 'int64', 'description' => 'Maximum value to enforce for new documents.', 'default' => null, 'required' => false, From bfac0f92af79e9c9f6c65c476b7966c5b27fca23 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 13 Jan 2026 17:11:29 +0530 Subject: [PATCH 18/52] chore: update domains lib --- composer.json | 4 +- composer.lock | 157 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 102 insertions(+), 59 deletions(-) diff --git a/composer.json b/composer.json index e4a268f546..ef833cfb38 100644 --- a/composer.json +++ b/composer.json @@ -54,9 +54,9 @@ "utopia-php/config": "1.*", "utopia-php/database": "4.*", "utopia-php/detector": "0.2.*", - "utopia-php/domains": "0.9.*", + "utopia-php/domains": "0.11.*", "utopia-php/emails": "0.6.*", - "utopia-php/dns": "1.4.*", + "utopia-php/dns": "1.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", "utopia-php/fetch": "0.5.*", diff --git a/composer.lock b/composer.lock index 8b68b2a1ba..20b5c754eb 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": "ad3d3cc3b265daf8657cb43836fc9879", + "content-hash": "2d32f0fe31dc03c1f96a2582093afca1", "packages": [ { "name": "adhocore/jwt", @@ -3552,23 +3552,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "27d66630f528473cb563bbcf362d7d9a711b384e" + "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/27d66630f528473cb563bbcf362d7d9a711b384e", - "reference": "27d66630f528473cb563bbcf362d7d9a711b384e", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/662244bd170bab3ba45fd4470ac2e5a36c980131", + "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131", "shasum": "" }, "require": { "php": ">=8.0", "utopia-php/database": "4.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3595,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.2" + "source": "https://github.com/utopia-php/audit/tree/2.0.3" }, - "time": "2026-01-07T07:01:25+00:00" + "time": "2026-01-13T09:49:40+00:00" }, { "name": "utopia-php/auth", @@ -4001,22 +4001,22 @@ }, { "name": "utopia-php/dns", - "version": "1.4.1", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/utopia-php/dns.git", - "reference": "5daf8b683dad877491c4df84c6be24850b2f363b" + "reference": "a1f490ba425b1a5128e7aaa24eff560900812d21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dns/zipball/5daf8b683dad877491c4df84c6be24850b2f363b", - "reference": "5daf8b683dad877491c4df84c6be24850b2f363b", + "url": "https://api.github.com/repos/utopia-php/dns/zipball/a1f490ba425b1a5128e7aaa24eff560900812d21", + "reference": "a1f490ba425b1a5128e7aaa24eff560900812d21", "shasum": "" }, "require": { "php": ">=8.3", - "utopia-php/console": "0.0.*", - "utopia-php/domains": "0.9.*", + "utopia-php/domains": "0.11.*", + "utopia-php/span": "1.0.*", "utopia-php/telemetry": "*", "utopia-php/validators": "0.*" }, @@ -4052,22 +4052,22 @@ ], "support": { "issues": "https://github.com/utopia-php/dns/issues", - "source": "https://github.com/utopia-php/dns/tree/1.4.1" + "source": "https://github.com/utopia-php/dns/tree/1.5.3" }, - "time": "2025-12-17T09:09:08+00:00" + "time": "2026-01-13T11:39:38+00:00" }, { "name": "utopia-php/domains", - "version": "0.9.2", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/utopia-php/domains.git", - "reference": "52b654f8a0e170bfa2e54cb47755b256822477c7" + "reference": "f333e23e721ca5cd3bd21063fa88304114b0467d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/domains/zipball/52b654f8a0e170bfa2e54cb47755b256822477c7", - "reference": "52b654f8a0e170bfa2e54cb47755b256822477c7", + "url": "https://api.github.com/repos/utopia-php/domains/zipball/f333e23e721ca5cd3bd21063fa88304114b0467d", + "reference": "f333e23e721ca5cd3bd21063fa88304114b0467d", "shasum": "" }, "require": { @@ -4114,9 +4114,9 @@ ], "support": { "issues": "https://github.com/utopia-php/domains/issues", - "source": "https://github.com/utopia-php/domains/tree/0.9.2" + "source": "https://github.com/utopia-php/domains/tree/0.11.0" }, - "time": "2025-11-26T12:16:36+00:00" + "time": "2026-01-13T09:40:08+00:00" }, { "name": "utopia-php/dsn", @@ -4167,22 +4167,22 @@ }, { "name": "utopia-php/emails", - "version": "0.6.4", + "version": "0.6.5", "source": { "type": "git", "url": "https://github.com/utopia-php/emails.git", - "reference": "fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52" + "reference": "178e57a0f9a24139500c94ce73d166800197b6cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/emails/zipball/fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52", - "reference": "fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52", + "url": "https://api.github.com/repos/utopia-php/emails/zipball/178e57a0f9a24139500c94ce73d166800197b6cf", + "reference": "178e57a0f9a24139500c94ce73d166800197b6cf", "shasum": "" }, "require": { "php": ">=8.0", "utopia-php/cli": "^0.15", - "utopia-php/domains": "^0.9", + "utopia-php/domains": "^0.11", "utopia-php/fetch": "^0.5", "utopia-php/validators": "0.*" }, @@ -4221,9 +4221,9 @@ ], "support": { "issues": "https://github.com/utopia-php/emails/issues", - "source": "https://github.com/utopia-php/emails/tree/0.6.4" + "source": "https://github.com/utopia-php/emails/tree/0.6.5" }, - "time": "2025-12-18T16:36:50+00:00" + "time": "2026-01-13T09:55:59+00:00" }, { "name": "utopia-php/fetch", @@ -4266,23 +4266,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.36", + "version": "0.33.37", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" + "reference": "30a119d76531d89da9240496940c84fcd9e1758b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", + "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", + "reference": "30a119d76531d89da9240496940c84fcd9e1758b", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4308,9 +4308,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.36" + "source": "https://github.com/utopia-php/http/tree/0.33.37" }, - "time": "2026-01-12T07:32:29+00:00" + "time": "2026-01-13T10:10:21+00:00" }, { "name": "utopia-php/image", @@ -4515,16 +4515,16 @@ }, { "name": "utopia-php/migration", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2" + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/4cb7a0e65a36058d153ef5643090414c6525e4a2", - "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", "shasum": "" }, "require": { @@ -4564,9 +4564,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.4.2" + "source": "https://github.com/utopia-php/migration/tree/1.4.3" }, - "time": "2026-01-08T04:46:18+00:00" + "time": "2026-01-13T09:51:08+00:00" }, { "name": "utopia-php/mongo", @@ -4953,6 +4953,49 @@ }, "time": "2021-03-10T10:45:22+00:00" }, + { + "name": "utopia-php/span", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/span.git", + "reference": "f2f6c499ded3a776e8019902e83d140ff0f89693" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/span/zipball/f2f6c499ded3a776e8019902e83d140ff0f89693", + "reference": "f2f6c499ded3a776e8019902e83d140ff0f89693", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "laravel/pint": "^1.0", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.0", + "swoole/ide-helper": "^5.0" + }, + "suggest": { + "ext-swoole": "Required for coroutine-based storage" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Span\\": "src/Span/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Simple span tracing library for PHP with coroutine support", + "support": { + "issues": "https://github.com/utopia-php/span/issues", + "source": "https://github.com/utopia-php/span/tree/1.0.0" + }, + "time": "2026-01-12T20:05:10+00:00" + }, { "name": "utopia-php/storage", "version": "0.18.18", @@ -5013,22 +5056,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.6", + "version": "0.8.4", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.36" + "utopia-php/framework": "0.33.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5058,9 +5101,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.6" + "source": "https://github.com/utopia-php/swoole/tree/0.8.4" }, - "time": "2026-01-12T07:57:35+00:00" + "time": "2025-09-07T09:39:46+00:00" }, { "name": "utopia-php/system", @@ -5170,16 +5213,16 @@ }, { "name": "utopia-php/validators", - "version": "0.1.0", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", "shasum": "" }, "require": { @@ -5187,7 +5230,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", + "phpstan/phpstan": "2.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5209,9 +5252,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.1.0" + "source": "https://github.com/utopia-php/validators/tree/0.2.0" }, - "time": "2025-11-18T11:05:46+00:00" + "time": "2026-01-13T09:16:51+00:00" }, { "name": "utopia-php/vcs", @@ -8968,5 +9011,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } From 432e86ec07365a41be98ee90442c9b846eb0838b Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 13 Jan 2026 18:04:14 +0530 Subject: [PATCH 19/52] regen specs. --- app/config/specs/open-api3-latest-console.json | 4 ++-- app/config/specs/open-api3-latest-server.json | 4 ++-- app/config/specs/swagger2-latest-console.json | 4 ++-- app/config/specs/swagger2-latest-server.json | 4 ++-- src/Appwrite/Utopia/Response/Model/Message.php | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 617580e3e2..5bc41be4ce 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -61306,7 +61306,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -61352,7 +61352,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 076d8e837a..efe4d94118 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -45297,7 +45297,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -45343,7 +45343,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 38928664f8..4f93c34617 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -61248,7 +61248,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -61294,7 +61294,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 40e13396fc..3a4c411f64 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -45233,7 +45233,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -45279,7 +45279,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 4c1e08b9cb..95b965fa1a 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -98,7 +98,7 @@ class Message extends Model 'type' => self::TYPE_ENUM, 'description' => 'Status of delivery.', 'default' => 'draft', - 'example' => 'Message status can be one of the following: draft, processing, scheduled, sent, or failed.', + 'example' => 'processing', 'enum' => ['draft', 'processing', 'scheduled', 'sent', 'failed'], ]); } From 321fc8ee705c6f1022d84dc12fb267b85505b38d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 Jan 2026 02:37:17 +1300 Subject: [PATCH 20/52] Revert "Merge pull request #11099 from appwrite/feat-auth-instance" This reverts commit a4734a5de733d362b481ba731944202051b2e90b, reversing changes made to 15922fb88cd7f142137baa2b3a73b9435b8603cd. # Conflicts: # composer.lock --- app/cli.php | 28 +-- app/config/storage/resource_limits.php | 4 +- app/controllers/api/account.php | 146 ++++++-------- app/controllers/api/graphql.php | 5 +- app/controllers/api/health.php | 18 +- app/controllers/api/messaging.php | 65 +++--- app/controllers/api/migrations.php | 14 +- app/controllers/api/project.php | 9 +- app/controllers/api/teams.php | 63 +++--- app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 60 +++--- app/controllers/general.php | 187 +++++++++--------- app/controllers/shared/api.php | 53 +++-- app/controllers/shared/api/auth.php | 7 +- app/http.php | 28 ++- app/init/database/filters.php | 47 ++--- app/init/resources.php | 106 +++++----- app/realtime.php | 41 ++-- app/worker.php | 53 ++--- composer.json | 10 +- composer.lock | 107 +++++----- src/Appwrite/Databases/TransactionState.php | 10 +- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Avatars/Http/Action.php | 10 +- .../Modules/Avatars/Http/Browsers/Get.php | 2 +- .../Avatars/Http/Cards/Cloud/Back/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/Front/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/OG/Get.php | 7 +- .../Modules/Avatars/Http/CreditCards/Get.php | 2 +- .../Modules/Avatars/Http/Flags/Get.php | 2 +- .../Platform/Modules/Compute/Base.php | 41 +--- .../Modules/Console/Http/Resources/Get.php | 6 +- .../Collections/Attributes/Action.php | 10 +- .../Collections/Attributes/Boolean/Create.php | 6 +- .../Collections/Attributes/Boolean/Update.php | 5 +- .../Attributes/Datetime/Create.php | 7 +- .../Attributes/Datetime/Update.php | 5 +- .../Collections/Attributes/Delete.php | 5 +- .../Collections/Attributes/Email/Create.php | 7 +- .../Collections/Attributes/Email/Update.php | 5 +- .../Collections/Attributes/Enum/Create.php | 7 +- .../Collections/Attributes/Enum/Update.php | 5 +- .../Collections/Attributes/Float/Create.php | 6 +- .../Collections/Attributes/Float/Update.php | 5 +- .../Databases/Collections/Attributes/Get.php | 5 +- .../Collections/Attributes/IP/Create.php | 7 +- .../Collections/Attributes/IP/Update.php | 5 +- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Integer/Update.php | 5 +- .../Collections/Attributes/Line/Create.php | 6 +- .../Collections/Attributes/Line/Update.php | 5 +- .../Collections/Attributes/Point/Create.php | 6 +- .../Collections/Attributes/Point/Update.php | 5 +- .../Collections/Attributes/Polygon/Create.php | 6 +- .../Collections/Attributes/Polygon/Update.php | 5 +- .../Attributes/Relationship/Create.php | 7 +- .../Attributes/Relationship/Update.php | 6 +- .../Collections/Attributes/String/Create.php | 8 +- .../Collections/Attributes/String/Update.php | 6 +- .../Collections/Attributes/URL/Create.php | 7 +- .../Collections/Attributes/URL/Update.php | 6 +- .../Collections/Attributes/XList.php | 5 +- .../Http/Databases/Collections/Create.php | 5 +- .../Http/Databases/Collections/Delete.php | 5 +- .../Collections/Documents/Action.php | 7 +- .../Documents/Attribute/Decrement.php | 13 +- .../Documents/Attribute/Increment.php | 13 +- .../Collections/Documents/Create.php | 43 ++-- .../Collections/Documents/Delete.php | 17 +- .../Databases/Collections/Documents/Get.php | 12 +- .../Collections/Documents/Logs/XList.php | 5 +- .../Collections/Documents/Update.php | 26 ++- .../Collections/Documents/Upsert.php | 26 ++- .../Databases/Collections/Documents/XList.php | 16 +- .../Http/Databases/Collections/Get.php | 5 +- .../Databases/Collections/Indexes/Create.php | 5 +- .../Databases/Collections/Indexes/Delete.php | 5 +- .../Databases/Collections/Indexes/Get.php | 5 +- .../Databases/Collections/Indexes/XList.php | 7 +- .../Http/Databases/Collections/Logs/XList.php | 39 ++-- .../Http/Databases/Collections/Update.php | 5 +- .../Http/Databases/Collections/Usage/Get.php | 5 +- .../Http/Databases/Collections/XList.php | 5 +- .../Http/Databases/Transactions/Create.php | 5 +- .../Transactions/Operations/Create.php | 34 ++-- .../Http/Databases/Transactions/Update.php | 37 ++-- .../Databases/Http/Databases/Usage/Get.php | 5 +- .../Databases/Http/Databases/Usage/XList.php | 5 +- .../Tables/Columns/Boolean/Create.php | 1 - .../Tables/Columns/Boolean/Update.php | 1 - .../Tables/Columns/Datetime/Create.php | 1 - .../Tables/Columns/Datetime/Update.php | 1 - .../Http/TablesDB/Tables/Columns/Delete.php | 1 - .../TablesDB/Tables/Columns/Email/Create.php | 1 - .../TablesDB/Tables/Columns/Email/Update.php | 1 - .../TablesDB/Tables/Columns/Enum/Create.php | 1 - .../TablesDB/Tables/Columns/Enum/Update.php | 1 - .../TablesDB/Tables/Columns/Float/Create.php | 1 - .../TablesDB/Tables/Columns/Float/Update.php | 1 - .../Http/TablesDB/Tables/Columns/Get.php | 1 - .../TablesDB/Tables/Columns/IP/Create.php | 1 - .../TablesDB/Tables/Columns/IP/Update.php | 1 - .../Tables/Columns/Integer/Create.php | 1 - .../Tables/Columns/Integer/Update.php | 1 - .../TablesDB/Tables/Columns/Line/Create.php | 1 - .../TablesDB/Tables/Columns/Line/Update.php | 1 - .../TablesDB/Tables/Columns/Point/Create.php | 1 - .../TablesDB/Tables/Columns/Point/Update.php | 1 - .../Tables/Columns/Polygon/Create.php | 1 - .../Tables/Columns/Polygon/Update.php | 1 - .../Tables/Columns/Relationship/Create.php | 1 - .../Tables/Columns/Relationship/Update.php | 1 - .../TablesDB/Tables/Columns/String/Create.php | 1 - .../TablesDB/Tables/Columns/String/Update.php | 1 - .../TablesDB/Tables/Columns/URL/Create.php | 1 - .../TablesDB/Tables/Columns/URL/Update.php | 1 - .../Http/TablesDB/Tables/Columns/XList.php | 1 - .../Databases/Http/TablesDB/Tables/Create.php | 1 - .../Databases/Http/TablesDB/Tables/Delete.php | 1 - .../Databases/Http/TablesDB/Tables/Get.php | 1 - .../Http/TablesDB/Tables/Indexes/Create.php | 2 - .../Http/TablesDB/Tables/Indexes/Delete.php | 1 - .../Http/TablesDB/Tables/Indexes/Get.php | 1 - .../Http/TablesDB/Tables/Indexes/XList.php | 1 - .../Http/TablesDB/Tables/Logs/XList.php | 1 - .../Http/TablesDB/Tables/Rows/Bulk/Delete.php | 1 - .../Http/TablesDB/Tables/Rows/Bulk/Update.php | 1 - .../Http/TablesDB/Tables/Rows/Bulk/Upsert.php | 1 - .../TablesDB/Tables/Rows/Column/Decrement.php | 1 - .../TablesDB/Tables/Rows/Column/Increment.php | 1 - .../Http/TablesDB/Tables/Rows/Create.php | 1 - .../Http/TablesDB/Tables/Rows/Delete.php | 1 - .../Http/TablesDB/Tables/Rows/Get.php | 1 - .../Http/TablesDB/Tables/Rows/Logs/XList.php | 1 - .../Http/TablesDB/Tables/Rows/Update.php | 1 - .../Http/TablesDB/Tables/Rows/Upsert.php | 1 - .../Http/TablesDB/Tables/Rows/XList.php | 1 - .../Databases/Http/TablesDB/Tables/Update.php | 1 - .../Http/TablesDB/Tables/Usage/Get.php | 1 - .../Databases/Http/TablesDB/Tables/XList.php | 1 - .../Http/TablesDB/Transactions/Create.php | 1 - .../Transactions/Operations/Create.php | 1 - .../Http/TablesDB/Transactions/Update.php | 1 - .../Databases/Http/TablesDB/Usage/Get.php | 1 - .../Databases/Http/TablesDB/Usage/XList.php | 1 - .../Functions/Http/Deployments/Create.php | 5 +- .../Http/Deployments/Template/Create.php | 12 +- .../Functions/Http/Deployments/Vcs/Create.php | 2 +- .../Functions/Http/Executions/Create.php | 25 ++- .../Functions/Http/Executions/Delete.php | 6 +- .../Modules/Functions/Http/Executions/Get.php | 10 +- .../Functions/Http/Executions/XList.php | 10 +- .../Functions/Http/Functions/Create.php | 9 +- .../Functions/Http/Functions/Delete.php | 6 +- .../Http/Functions/Deployment/Update.php | 10 +- .../Functions/Http/Functions/Update.php | 6 +- .../Modules/Functions/Http/Usage/Get.php | 5 +- .../Modules/Functions/Http/Usage/XList.php | 5 +- .../Functions/Http/Variables/Create.php | 6 +- .../Functions/Http/Variables/Delete.php | 6 +- .../Functions/Http/Variables/Update.php | 6 +- .../Modules/Functions/Workers/Builds.php | 8 +- .../Modules/Sites/Http/Deployments/Create.php | 10 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Template/Create.php | 9 +- .../Sites/Http/Deployments/Vcs/Create.php | 6 +- .../Sites/Http/Sites/Deployment/Update.php | 8 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 6 +- .../Modules/Sites/Http/Usage/XList.php | 5 +- .../Storage/Http/Buckets/Files/Create.php | 36 ++-- .../Storage/Http/Buckets/Files/Delete.php | 22 +-- .../Http/Buckets/Files/Download/Get.php | 18 +- .../Storage/Http/Buckets/Files/Get.php | 16 +- .../Http/Buckets/Files/Preview/Get.php | 22 +-- .../Storage/Http/Buckets/Files/Push/Get.php | 12 +- .../Storage/Http/Buckets/Files/Update.php | 24 ++- .../Storage/Http/Buckets/Files/View/Get.php | 18 +- .../Storage/Http/Buckets/Files/XList.php | 22 +-- .../Modules/Storage/Http/Buckets/Get.php | 23 +-- .../Modules/Storage/Http/Buckets/XList.php | 35 ++-- .../Modules/Storage/Http/Usage/Get.php | 5 +- .../Modules/Storage/Http/Usage/XList.php | 5 +- .../Http/Tokens/Buckets/Files/Action.php | 17 +- .../Http/Tokens/Buckets/Files/Create.php | 11 +- .../Http/Tokens/Buckets/Files/XList.php | 6 +- src/Appwrite/Platform/Tasks/Migrate.php | 9 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 3 +- .../Platform/Tasks/StatsResources.php | 5 +- .../Platform/Workers/Certificates.php | 33 +--- src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Platform/Workers/Functions.php | 2 + src/Appwrite/Platform/Workers/Migrations.php | 31 ++- .../Utopia/Database/Documents/User.php | 5 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 5 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 25 +-- .../DatabasesPermissionsGuestTest.php | 25 +-- tests/e2e/Services/Tokens/TokensBase.php | 8 +- .../unit/Messaging/MessagingChannelsTest.php | 18 +- .../Utopia/Database/Documents/UserTest.php | 33 ++-- 202 files changed, 978 insertions(+), 1479 deletions(-) diff --git a/app/cli.php b/app/cli.php index 7493d10ab3..07966b2450 100644 --- a/app/cli.php +++ b/app/cli.php @@ -41,6 +41,8 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false)); // require controllers after overwriting runtimes require_once __DIR__ . '/controllers/general.php'; +Authorization::disable(); + CLI::setResource('register', fn () => $register); CLI::setResource('cache', function ($pools) { @@ -58,13 +60,7 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('authorization', function () { - $authorization = new Authorization(); - $authorization->disable(); - return $authorization; -}, []); - -CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { +CLI::setResource('dbForPlatform', function ($pools, $cache) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -78,7 +74,6 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform - ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -104,7 +99,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { } return $dbForPlatform; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); CLI::setResource('console', function () { return new Document(Config::getParam('console')); @@ -115,10 +110,10 @@ CLI::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) { +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -151,7 +146,6 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -168,18 +162,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database - ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); return $database; }; -}, ['pools', 'dbForPlatform', 'cache', 'authorization']); +}, ['pools', 'dbForPlatform', 'cache']); -CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { +CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { + return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -189,7 +182,6 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) @@ -202,7 +194,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); CLI::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); diff --git a/app/config/storage/resource_limits.php b/app/config/storage/resource_limits.php index 43ed2b8b05..cfbcea5a47 100644 --- a/app/config/storage/resource_limits.php +++ b/app/config/storage/resource_limits.php @@ -3,6 +3,4 @@ use Utopia\Image\Image; use Utopia\System\System; -if (\class_exists('Imagick')) { - Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); -} +Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index bcea3387a2..2c481b500c 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -207,10 +207,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr } -$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode, Authorization $authorization) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) { /** @var Appwrite\Utopia\Database\Documents\User $userFromRequest */ - $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -266,7 +266,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -275,7 +275,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - $authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -376,9 +376,8 @@ App::post('/v1/account') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('authorization') ->inject('hooks') - ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Hooks $hooks) { + ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Hooks $hooks) { $email = \strtolower($email); if ('console' === $project->getId()) { @@ -470,9 +469,9 @@ App::post('/v1/account') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -498,9 +497,9 @@ App::post('/v1/account') throw new Exception(Exception::USER_ALREADY_EXISTS); } - $authorization->removeRole(Role::guests()->toString()); - $authorization->addRole(Role::user($user->getId())->toString()); - $authorization->addRole(Role::users()->toString()); + Authorization::unsetRole(Role::guests()->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::users()->toString()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -977,8 +976,7 @@ App::post('/v1/account/sessions/email') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -1023,7 +1021,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) { @@ -1122,8 +1120,7 @@ App::post('/v1/account/sessions/anonymous') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->inject('authorization') - ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1168,7 +1165,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; @@ -1194,7 +1191,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -1277,7 +1274,6 @@ App::post('/v1/account/sessions/token') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') -->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1474,8 +1470,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) { + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1731,7 +1726,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ]); $user->removeAttribute('$sequence'); - $userDoc = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), @@ -1749,8 +1744,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - $authorization->addRole(Role::user($user->getId())->toString()); - $authorization->addRole(Role::users()->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::users()->toString()); if (false === $user->getAttribute('status')) { // Account is blocked $failureRedirect(Exception::USER_BLOCKED); // User is in status blocked @@ -1821,7 +1816,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1845,7 +1840,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2082,8 +2077,7 @@ App::post('/v1/account/tokens/magic-url') ->inject('queueForMails') ->inject('proofForPassword') ->inject('platform') - ->inject('authorization') - ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform, Authorization $authorization) { + ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2156,7 +2150,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); @@ -2176,7 +2170,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2362,8 +2356,7 @@ App::post('/v1/account/tokens/email') ->inject('queueForMails') ->inject('proofForPassword') ->inject('proofForCode') - ->inject('authorization') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2432,9 +2425,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2472,7 +2465,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2669,11 +2662,10 @@ App::put('/v1/account/sessions/magic-url') ->inject('queueForMails') ->inject('store') ->inject('proofForCode') - ->inject('authorization') - ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode, $authorization) use ($createSession) { + ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) { $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); $proofForToken->setHash(new Sha()); - $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode, $authorization); + $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode); }); App::put('/v1/account/sessions/phone') @@ -2719,7 +2711,6 @@ App::put('/v1/account/sessions/phone') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') - ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2763,8 +2754,7 @@ App::post('/v1/account/tokens/phone') ->inject('plan') ->inject('store') ->inject('proofForCode') - ->inject('authorization') - ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2814,9 +2804,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2862,7 +2852,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3253,8 +3243,7 @@ App::patch('/v1/account/email') ->inject('project') ->inject('hooks') ->inject('proofForPassword') - ->inject('authorization') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3306,7 +3295,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ + $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3322,7 +3311,7 @@ App::patch('/v1/account/email') $oldTarget = $user->find('identifier', $oldEmail, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); + Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate) { @@ -3363,9 +3352,8 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') -->inject('authorization') - ->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { + ->inject('proofForPassword') + ->action(function (string $phone, string $password, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3380,7 +3368,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ + $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3411,7 +3399,7 @@ App::patch('/v1/account/phone') $oldTarget = $user->find('identifier', $oldPhone, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); + Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate $th) { @@ -3547,9 +3535,7 @@ App::post('/v1/account/recovery') ->inject('queueForMails') ->inject('queueForEvents') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { - + ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -3585,7 +3571,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3741,8 +3727,7 @@ App::put('/v1/account/recovery') ->inject('hooks') ->inject('proofForPassword') ->inject('proofForToken') -->inject('authorization') - ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ $profile = $dbForProject->getDocument('users', $userId); @@ -3756,7 +3741,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $newPassword = $proofForPassword->hash($password); @@ -3859,8 +3844,7 @@ App::post('/v1/account/verifications/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3889,7 +3873,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4088,10 +4072,9 @@ App::put('/v1/account/verifications/email') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4103,7 +4086,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -4163,8 +4146,7 @@ App::post('/v1/account/verifications/phone') ->inject('queueForStatsUsage') ->inject('plan') ->inject('proofForCode') - ->inject('authorization') - ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -4203,7 +4185,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4309,10 +4291,9 @@ App::put('/v1/account/verifications/phone') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForCode') - ->inject('authorization') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4324,7 +4305,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -4377,13 +4358,12 @@ App::post('/v1/account/targets/push') ->inject('dbForProject') ->inject('store') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); @@ -4458,10 +4438,9 @@ App::put('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { + ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); @@ -4524,9 +4503,8 @@ App::delete('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) { + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index e0cc4181db..baf0ba1512 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -28,12 +28,11 @@ use Utopia\Validator\Text; App::init() ->groups(['graphql']) ->inject('project') - ->inject('authorization') - ->action(function (Document $project, Authorization $authorization) { + ->action(function (Document $project) { if ( array_key_exists('graphql', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['graphql'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index d6388185d3..907ed54de8 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -27,7 +27,6 @@ use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Config\Config; use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -102,8 +101,7 @@ App::get('/v1/health/db') )) ->inject('response') ->inject('pools') - ->inject('authorization') - ->action(action: function (Response $response, Group $pools, Authorization $authorization) { + ->action(function (Response $response, Group $pools) { $output = []; $failures = []; @@ -116,14 +114,14 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); - $adapter->setAuthorization($authorization); + $checkStart = \microtime(true); if ($adapter->ping()) { $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $failures[] = $database; @@ -134,8 +132,6 @@ App::get('/v1/health/db') } } - // Only throw error if ALL databases failed (no successful pings) - // This allows partial failures in environments where not all DBs are ready if (!empty($failures)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); } @@ -185,7 +181,7 @@ App::get('/v1/health/cache') $output[] = new Document([ 'name' => $key . " ($cache)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $failures[] = $cache; @@ -245,7 +241,7 @@ App::get('/v1/health/pubsub') $output[] = new Document([ 'name' => $key . " ($pubsub)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $failures[] = $pubsub; @@ -827,7 +823,7 @@ App::get('/v1/health/storage/local') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -879,7 +875,7 @@ App::get('/v1/health/storage') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 6ac36fe3c0..0b6a314dc5 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -36,7 +36,6 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -1074,9 +1073,8 @@ App::get('/v1/messaging/providers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1102,7 +1100,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); @@ -2483,9 +2481,8 @@ App::get('/v1/messaging/topics') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2511,7 +2508,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Topic '{$topicId}' for the 'cursor' value not found."); @@ -2785,27 +2782,29 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) { $subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId; - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); } - if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + + $validator = new Authorization('subscribe'); + + if (!$validator->isValid($topic->getAttribute('subscribe'))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2838,7 +2837,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute( + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2883,9 +2882,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2896,7 +2894,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2919,7 +2917,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Subscriber '{$subscriberId}' for the 'cursor' value not found."); @@ -2933,10 +2931,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $authorization) { - return function () use ($subscriber, $dbForProject, $authorization) { - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) { + return function () use ($subscriber, $dbForProject) { + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); return $subscriber ->setAttribute('target', $target) @@ -3069,10 +3067,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Authorization $authorization, Response $response) { - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) { + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3084,8 +3081,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') throw new Exception(Exception::SUBSCRIBER_NOT_FOUND); } - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber ->setAttribute('target', $target) @@ -3121,10 +3118,9 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) { + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3147,7 +3143,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute( + Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3706,9 +3702,8 @@ App::get('/v1/messaging/messages') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3734,7 +3729,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('messages', $messageId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found."); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 1a17853577..3989ad3298 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -342,7 +342,6 @@ App::post('/v1/migrations/csv/imports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->inject('project') ->inject('platform') ->inject('deviceForFiles') @@ -357,7 +356,6 @@ App::post('/v1/migrations/csv/imports') Response $response, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, Document $project, array $platform, Device $deviceForFiles, @@ -365,7 +363,7 @@ App::post('/v1/migrations/csv/imports') Event $queueForEvents, Migration $queueForMigrations ) { - $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -376,7 +374,7 @@ App::post('/v1/migrations/csv/imports') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $authorization->skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -493,7 +491,6 @@ App::post('/v1/migrations/csv/exports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->inject('project') ->inject('platform') ->inject('queueForEvents') @@ -512,7 +509,6 @@ App::post('/v1/migrations/csv/exports') Response $response, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, Document $project, array $platform, Event $queueForEvents, @@ -524,7 +520,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -537,12 +533,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $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 = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index cda03f923a..a57675d3e8 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -45,10 +45,9 @@ App::get('/v1/project/usage') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('authorization') ->inject('getLogsDB') ->inject('smsRates') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, Authorization $authorization, callable $getLogsDB, array $smsRates) { + ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -103,7 +102,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - $authorization->skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { + Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; @@ -287,7 +286,7 @@ App::get('/v1/project/usage') }, $dbForProject->find('functions')); // This total is includes free and paid SMS usage - $authPhoneTotal = $authorization->skip(fn () => $dbForProject->sum('stats', 'value', [ + $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), @@ -295,7 +294,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = $authorization->skip(fn () => $dbForProject->find('stats', [ + $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index aa67a90885..1f8555b6cd 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -86,17 +86,16 @@ App::post('/v1/teams') ->inject('response') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { + ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAppUser = User::isApp(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)), @@ -492,7 +491,6 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -502,9 +500,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('plan') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { - $isAppUser = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + ->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 $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { + $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -621,13 +619,13 @@ App::post('/v1/teams/:teamId/memberships') ]); try { - $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', $userDocument)); + $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); 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'); @@ -663,11 +661,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - $authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { $membership->setAttribute('secret', $proofForToken->hash($secret)); @@ -679,7 +677,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - $authorization->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } else { throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); @@ -865,8 +863,7 @@ App::get('/v1/teams/:teamId/memberships') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { + ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -936,7 +933,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1007,8 +1004,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { + ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject) { $team = $dbForProject->getDocument('teams', $teamId); @@ -1028,7 +1024,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1107,9 +1103,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1126,9 +1121,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); - $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAppUser = User::isApp(Authorization::getRoles()); + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { // Quick check: fetch up to 2 owners to determine if only one exists @@ -1209,13 +1204,12 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') ->inject('store') ->inject('proofForToken') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1224,7 +1218,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::MEMBERSHIP_NOT_FOUND); } - $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); @@ -1260,11 +1254,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->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))); // Create session for the user if not logged in if (!$hasSession) { - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1292,7 +1286,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - $authorization->addRole(Role::user($userId)->toString()); + Authorization::setRole(Role::user($userId)->toString()); $encoded = $store ->setProperty('id', $user->getId()) @@ -1330,7 +1324,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1374,9 +1368,8 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('project') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1434,7 +1427,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members - $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); + Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); } $queueForEvents diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index a963284538..bbe1d8a84a 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2678,8 +2678,8 @@ App::get('/v1/users/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { + ->inject('register') + ->action(function (string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -2689,7 +2689,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 2270f4fd89..4249dbfd48 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -76,7 +76,7 @@ use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Authorization $authorization, Build $queueForBuilds, callable $getProjectDB, Request $request, array $platform) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, array $platform) { $errors = []; foreach ($repositories as $repository) { try { @@ -87,12 +87,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); - $resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -141,7 +141,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -180,7 +180,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } else { @@ -191,7 +191,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = $authorization->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ + $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -212,7 +212,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -251,7 +251,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -294,7 +294,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -334,7 +334,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); - $authorization->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); + Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); @@ -344,7 +344,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -377,7 +377,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -408,7 +408,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -460,7 +460,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if ($lockAcquired) { // Wrap in try/finally to ensure lock file gets deleted try { - $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : ''; @@ -472,7 +472,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()); } } finally { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -1476,12 +1476,11 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') - ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1517,14 +1516,14 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find resourceId from relevant resources table - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push (not committed by us) and not when branch is created or deleted if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1537,16 +1536,16 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - $authorization->skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -1575,12 +1574,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1589,7 +1588,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1600,7 +1599,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1787,18 +1786,17 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') - ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = $authorization->skip(fn () => $dbForPlatform->findOne('repositories', [ + $repository = Authorization::skip(fn () => $dbForPlatform->findOne('repositories', [ Query::equal('$id', [$repositoryId]), Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1816,7 +1814,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1848,7 +1846,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerCommitMessage = $pullRequestResponse['title'] ?? ''; $providerCommitUrl = $pullRequestResponse['html_url'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index 671c948e93..ec8cfef775 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -59,7 +59,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -67,16 +67,16 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } // TODO: (@Meldiron) Remove after 1.7.x migration - if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); - } else { - $rule = $authorization->skip( - fn () => $dbForPlatform->find('rules', [ - Query::equal('domain', [$host]), - Query::limit(1) - ]) - )[0] ?? new Document(); - } + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $rule = Authorization::skip(function () use ($dbForPlatform, $host, $isMd5) { + if ($isMd5) { + return $dbForPlatform->getDocument('rules', md5($host)); + } + + return $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$host]), + ]) ?? new Document(); + }); $errorView = __DIR__ . '/../views/general/error.phtml'; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -111,7 +111,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = $authorization->skip( + $project = Authorization::skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -119,7 +119,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -158,7 +158,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw /** @var Document $deployment */ if (!empty($rule->getAttribute('deploymentId', ''))) { - $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); } else { // 1.6.x DB schema compatibility // TODO: Make sure deploymentId is never empty, and remove this code @@ -172,15 +172,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // Document of site or function $resource = $resourceType === 'function' ? - $authorization->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : - $authorization->skip(fn () => $dbForProject->getDocument('sites', $resourceId)); + Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : + Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId)); // ID of active deployments // Attempts to use attribute from both schemas (1.6 and 1.7) $activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', '')); // Get deployment document, as intended originally - $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -199,8 +199,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $resource = $type === 'function' ? - $authorization->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : - $authorization->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); + Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); @@ -242,7 +242,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $userExists = false; $userId = $payload['userId'] ?? ''; if (!empty($userId)) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -255,7 +255,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); if (!$project->isEmpty() && isset($user)) { $teamId = $project->getAttribute('teamId', ''); $membership = $user->find('teamId', $teamId, 'memberships'); @@ -862,16 +862,15 @@ App::init() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors) { /* * Appwrite Router */ $hostname = $request->getHostname() ?? ''; $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain - if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (!in_array($hostname, $platformHostnames) || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1034,8 +1033,7 @@ App::init() ->inject('dbForPlatform') ->inject('queueForCertificates') ->inject('platform') - ->inject('authorization') - ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) { + ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform) { $hostname = $request->getHostname(); $cache = Config::getParam('hostnames', []); $platformHostnames = $platform['hostnames'] ?? []; @@ -1063,64 +1061,64 @@ App::init() } // 4. Check/create rule (requires DB access) - $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) { - try { - // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $document = $isMd5 - ? $dbForPlatform->getDocument('rules', md5($domain->get())) - : $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$domain->get()]), - ]); - - if (!$document->isEmpty()) { - return; - } - - // 5. Create new rule - $owner = ''; - $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); - $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - - if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { - $funcDomain = $fallback; - } - - if ( - (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || - (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) - ) { - $owner = 'Appwrite'; - } - - $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); - $document = new Document([ - '$id' => $ruleId, - 'domain' => $domain->get(), - 'type' => 'api', - 'status' => 'verifying', - 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), - 'search' => implode(' ', [$ruleId, $domain->get()]), - 'owner' => $owner, - 'region' => $console->getAttribute('region') + Authorization::disable(); + try { + // TODO: (@Meldiron) Remove after 1.7.x migration + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $document = $isMd5 + ? $dbForPlatform->getDocument('rules', md5($domain->get())) + : $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]), ]); - $dbForPlatform->createDocument('rules', $document); - - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); - $queueForCertificates - ->setDomain($document) - ->setSkipRenewCheck(true) - ->trigger(); - } catch (Duplicate $e) { - Console::info('Certificate already exists'); - } finally { - $cache[$domain->get()] = true; - Config::setParam('hostnames', $cache); + if (!$document->isEmpty()) { + return; } - }); + + // 5. Create new rule + $owner = ''; + $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); + $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { + $funcDomain = $fallback; + } + + if ( + (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || + (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) + ) { + $owner = 'Appwrite'; + } + + $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); + $document = new Document([ + '$id' => $ruleId, + 'domain' => $domain->get(), + 'type' => 'api', + 'status' => 'verifying', + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getSequence(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') + ]); + + $dbForPlatform->createDocument('rules', $document); + + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + $queueForCertificates + ->setDomain($document) + ->setSkipRenewCheck(true) + ->trigger(); + } catch (Duplicate $e) { + Console::info('Certificate already exists'); + } finally { + $cache[$domain->get()] = true; + Config::setParam('hostnames', $cache); + Authorization::reset(); + } }); App::options() @@ -1143,8 +1141,7 @@ App::options() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors) { /* * Appwrite Router */ @@ -1185,8 +1182,7 @@ App::error() ->inject('log') ->inject('queueForStatsUsage') ->inject('devKey') - ->inject('authorization') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Document $devKey, Authorization $authorization) { + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1268,7 +1264,7 @@ App::error() * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { - if (!DBUser::isPrivileged($authorization->getRoles())) { + if (!DBUser::isPrivileged(Authorization::getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1330,7 +1326,7 @@ App::error() $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', $authorization->getRoles()); + $log->addExtra('roles', Authorization::getRoles()); try { /* add queries to log */ @@ -1534,14 +1530,13 @@ App::get('/robots.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1567,14 +1562,13 @@ App::get('/humans.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1658,8 +1652,7 @@ App::get('/v1/ping') ->inject('project') ->inject('dbForPlatform') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents, Authorization $authorization) { + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { if ($project->isEmpty() || $project->getId() === 'console') { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1671,7 +1664,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - $authorization->skip(function () use ($dbForPlatform, $project) { + Authorization::skip(function () use ($dbForPlatform, $project) { $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 23bbb12183..05c08a2231 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -30,7 +30,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Queue\Publisher; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; @@ -234,8 +233,7 @@ App::init() ->inject('mode') ->inject('team') ->inject('apiKey') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) { + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { $route = $utopia->getRoute(); /** @@ -320,7 +318,7 @@ App::init() // Handle special app role case if ($apiKey->getRole() === User::ROLE_APPS) { // Disable authorization checks for API keys - $authorization->setDefaultStatus(false); + Authorization::setDefaultStatus(false); $user = new User([ '$id' => '', @@ -394,14 +392,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. + Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - $authorization->addRole($role); - foreach ($user->getRoles($authorization) as $authRole) { - $authorization->addRole($authRole); + Authorization::setRole($role); + foreach ($user->getRoles() as $authRole) { + Authorization::setRole($authRole); } // Step 6: Update project and user last activity @@ -409,7 +407,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -444,7 +442,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -511,15 +509,14 @@ App::init() ->inject('devKey') ->inject('telemetry') ->inject('platform') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -549,7 +546,7 @@ App::init() $closestLimit = null; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -660,10 +657,10 @@ App::init() if ($useCache) { $route = $utopia->match($request); $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; - $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged($authorization->getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged(Authorization::getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -680,10 +677,10 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -694,7 +691,8 @@ App::init() } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -705,7 +703,7 @@ App::init() if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -716,11 +714,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!User::isPrivileged($authorization->getRoles())) { + if (!User::isPrivileged(Authorization::getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -816,9 +814,8 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->inject('authorization') ->inject('timelimit') - ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, callable $timelimit) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -979,11 +976,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', 0); $now = DateTime::now(); if ($cacheLog->isEmpty()) { - $authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([ + Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -993,7 +990,7 @@ App::shutdown() ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); - $authorization->skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); + Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); // Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load() $cache->save($key, $data['payload']); } @@ -1005,7 +1002,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!User::isPrivileged($authorization->getRoles())) { + if (!User::isPrivileged(Authorization::getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index c0f7494125..efa733fc34 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -36,8 +36,7 @@ App::init() ->inject('request') ->inject('project') ->inject('geodb') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) { + ->action(function (App $utopia, Request $request, Document $project, Reader $geodb) { $denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', ''); if (!empty($denylist && $project->getId() === 'console')) { $countries = explode(',', $denylist); @@ -50,8 +49,8 @@ App::init() $route = $utopia->match($request); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAppUser = User::isApp(Authorization::getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index 5d08c53eee..b7f857da48 100644 --- a/app/http.php +++ b/app/http.php @@ -27,6 +27,7 @@ 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\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Pools\Group; @@ -260,9 +261,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools); // create appwrite database, `dbForPlatform` is a direct access call. - createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections, $app) { - $authorization = $app->getResource('authorization'); - + createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) { if ($dbForPlatform->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) { $adapter = new AdapterDatabase($dbForPlatform); $audit = new Audit($adapter); @@ -322,9 +321,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } - if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - $authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('screenshots'), '$collection' => ID::custom('buckets'), 'name' => 'Screenshots', @@ -339,7 +338,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); Console::info(" └── Creating files collection for screenshots bucket..."); $files = $collections['buckets']['files'] ?? []; @@ -367,7 +366,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - $authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -459,12 +458,8 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool App::setResource('pools', fn () => $pools); try { - $authorization = $app->getResource('authorization'); - - $request->setAuthorization($authorization); - $response->setAuthorization($authorization); - $authorization->cleanRoles(); - $authorization->addRole(Role::any()->toString()); + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); $app->run($request, $response); } catch (\Throwable $th) { @@ -506,7 +501,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); $log->addExtra('trace', $th->getTraceAsString()); - $log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []); + $log->addExtra('roles', Authorization::getRoles()); $sdk = $route->getLabel("sdk", false); @@ -565,7 +560,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { /** @var Utopia\Database\Database $dbForPlatform */ $dbForPlatform = $app->getResource('dbForPlatform'); - Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) { + Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { try { $time = DateTime::now(); $limit = 1000; @@ -582,8 +577,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $authorization = $app->getResource('authorization'); - $results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries)); + $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); } catch (Throwable $th) { Console::error($th->getMessage()); } diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 2b2e17b6a9..c9ad3fce03 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -4,6 +4,7 @@ use Appwrite\OpenSSL\OpenSSL; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\System\System; Database::addFilter( @@ -69,11 +70,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [ + $attributes = $database->find('attributes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), - ])); + ]); foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); @@ -104,12 +105,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('indexes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), - ])); + ]); } ); @@ -119,11 +120,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('platforms', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -133,12 +134,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('keys', [ Query::equal('resourceType', ['projects']), Query::equal('resourceInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -148,11 +149,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('devKeys', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -162,11 +163,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('webhooks', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -176,7 +177,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database->find('sessions', [ + return Authorization::skip(fn () => $database->find('sessions', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); @@ -189,7 +190,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -203,7 +204,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('challenges', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -217,7 +218,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('authenticators', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -231,7 +232,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -251,14 +252,14 @@ Database::addFilter( default => ['function', 'site'] }; - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('variables', [ Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', $resourceType), Query::orderAsc('resourceType'), Query::orderAsc(), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -294,11 +295,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('variables', [ Query::equal('resourceType', ['project']), Query::limit(APP_LIMIT_SUBQUERY) - ])); + ]); } ); @@ -331,7 +332,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) @@ -345,7 +346,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $targetIds = $database->getAuthorization()->skip(fn () => \array_map( + $targetIds = Authorization::skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ Query::equal('topicInternalId', [$document->getSequence()]), diff --git a/app/init/resources.php b/app/init/resources.php index 371609da97..a3aa3ae47c 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -230,7 +230,7 @@ App::setResource('allowedSchemes', function (Document $project) { /** * Rule associated with a request origin. */ -App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) { +App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project) { $domain = \parse_url($request->getOrigin(), PHP_URL_HOST); if (empty($domain)) { return new Document(); @@ -238,7 +238,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do // TODO: (@Meldiron) Remove after 1.7.x migration $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = $authorization->skip(function () use ($dbForPlatform, $domain, $isMd5) { + $rule = Authorization::skip(function () use ($dbForPlatform, $domain, $isMd5) { if ($isMd5) { return $dbForPlatform->getDocument('rules', md5($domain)); } @@ -253,7 +253,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do } return $rule; -}, ['request', 'dbForPlatform', 'project', 'authorization']); +}, ['request', 'dbForPlatform', 'project']); /** * CORS service @@ -321,7 +321,7 @@ App::setResource('redirectValidator', function (Document $devKey, array $allowed return new Redirect($allowedHostnames, $allowedSchemes); }, ['devKey', 'allowedHostnames', 'allowedSchemes']); -App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken, $authorization) { +App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) { /** * Handles user authentication and session validation. * @@ -341,7 +341,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co * overwriting the previous value. */ - $authorization->setDefaultStatus(true); + Authorization::setDefaultStatus(true); $store->setKey('a_session_' . $project->getId()); @@ -408,7 +408,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co } // if (APP_MODE_ADMIN === $mode) { // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { - // $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. + // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. // } else { // $user = new Document([]); // } @@ -440,9 +440,9 @@ App::setResource('user', function (string $mode, Document $project, Document $co $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']); -App::setResource('project', function ($dbForPlatform, $request, $console, $authorization) { +App::setResource('project', function ($dbForPlatform, $request, $console) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ @@ -453,10 +453,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console, $autho return $console; } - $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForPlatform', 'request', 'console', 'authorization']); +}, ['dbForPlatform', 'request', 'console']); App::setResource('session', function (User $user, Store $store, Token $proofForToken) { if ($user->isEmpty()) { @@ -479,6 +479,10 @@ App::setResource('session', function (User $user, Store $store, Token $proofForT return; }, ['user', 'store', 'proofForToken']); +App::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + App::setResource('store', function (): Store { return new Store(); }); @@ -509,15 +513,7 @@ App::setResource('proofForCode', function (): Code { return $code; }); -App::setResource('console', function () { - return new Document(Config::getParam('console')); -}, []); - -App::setResource('authorization', function () { - return new Authorization(); -}, []); - -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Authorization $authorization) { +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -533,7 +529,6 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -555,15 +550,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); - -App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { +}, ['pools', 'dbForPlatform', 'cache', 'project']); +App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') @@ -573,12 +566,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authoriz $database->setDocumentType('users', User::class); return $database; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); -App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; - return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -590,15 +583,13 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $configure = (function (Database $database) use ($project, $dsn, $authorization) { + $configure = (function (Database $database) use ($project, $dsn) { $database - ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES) - ->setDocumentType('users', User::class) - ; + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + $database->setDocumentType('users', User::class); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -628,12 +619,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; }; -}, ['pools', 'dbForPlatform', 'cache', 'authorization']); +}, ['pools', 'dbForPlatform', 'cache']); -App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { +App::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $authorization, &$database) { + return function (?Document $project = null) use ($pools, $cache, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int) $project->getSequence()); return $database; @@ -643,7 +634,6 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -656,7 +646,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); App::setResource('audit', function ($dbForProject) { $adapter = new AdapterDatabase($dbForProject); @@ -855,7 +845,7 @@ App::setResource('promiseAdapter', function ($register) { return $register->get('promiseAdapter'); }, ['register']); -App::setResource('schema', function ($utopia, $dbForProject, $authorization) { +App::setResource('schema', function ($utopia, $dbForProject) { $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); @@ -865,8 +855,8 @@ App::setResource('schema', function ($utopia, $dbForProject, $authorization) { return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) { - $attrs = $authorization->skip(fn () => $dbForProject->find('attributes', [ + $attributes = function (int $limit, int $offset) use ($dbForProject) { + $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -940,7 +930,7 @@ App::setResource('schema', function ($utopia, $dbForProject, $authorization) { $urls, $params, ); -}, ['utopia', 'dbForProject', 'authorization']); +}, ['utopia', 'dbForProject']); App::setResource('gitHub', function (Cache $cache) { return new VcsGitHub($cache); @@ -968,7 +958,7 @@ App::setResource('smsRates', function () { return []; }); -App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform, Authorization $authorization) { +App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) { $devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', '')); // Check if given key match project's development keys @@ -987,7 +977,7 @@ App::setResource('devKey', function (Request $request, Document $project, array $accessedAt = $key->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -1004,15 +994,15 @@ App::setResource('devKey', function (Request $request, Document $project, array /** Update access time as well */ $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $key = $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } return $key; -}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']); +}, ['request', 'project', 'servers', 'dbForPlatform']); -App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request, Authorization $authorization) { +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { $teamInternalId = ''; if ($project->getId() !== 'console') { $teamInternalId = $project->getAttribute('teamInternalId', ''); @@ -1022,7 +1012,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A if (str_starts_with($path, '/v1/projects/:projectId')) { $uri = $request->getURI(); $pid = explode('/', $uri)[3]; - $p = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $pid)); + $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); @@ -1031,7 +1021,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -1040,14 +1030,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = $authorization->skip(function () use ($dbForPlatform, $teamInternalId) { + $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ Query::equal('$sequence', [$teamInternalId]), ]); }); return $team; -}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']); +}, ['project', 'dbForPlatform', 'utopia', 'request']); App::setResource( 'isResourceBlocked', @@ -1085,7 +1075,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key App::setResource('executor', fn () => new Executor()); -App::setResource('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) { +App::setResource('resourceToken', function ($project, $dbForProject, $request) { $tokenJWT = $request->getParam('token'); if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication @@ -1103,7 +1093,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A return new Document([]); } - $token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -1121,7 +1111,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A } return match ($token->getAttribute('resourceType')) { - TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject, $authorization) { + TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { $sequences = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); @@ -1132,7 +1122,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A $accessedAt = $token->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) { $token->setAttribute('accessedAt', DatabaseDateTime::now()); - $authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); + Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ @@ -1147,8 +1137,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A }; } return new Document([]); -}, ['project', 'dbForProject', 'request', 'authorization']); +}, ['project', 'dbForProject', 'request']); -App::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) { - return new TransactionState($dbForProject, $authorization); -}, ['dbForProject', 'authorization']); +App::setResource('transactionState', function (Database $dbForProject) { + return new TransactionState($dbForProject); +}, ['dbForProject']); diff --git a/app/realtime.php b/app/realtime.php index 31e6015d92..fab0ce7561 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -32,6 +32,7 @@ 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\DSN\DSN; use Utopia\Logger\Log; use Utopia\Pools\Group; @@ -308,7 +309,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume 'value' => '{}' ]); - $statsDocument = $database->getAuthorization()->skip(fn () => $database->createDocument('realtime', $document)); + $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); break; } catch (Throwable) { Console::warning("Collection not ready. Retrying connection ({$attempts})..."); @@ -338,7 +339,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume ->setAttribute('timestamp', DateTime::now()) ->setAttribute('value', json_encode($payload)); - $database->getAuthorization()->skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); + Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (Throwable $th) { $logError($th, "updateWorkerDocument"); } @@ -369,7 +370,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $payload = []; - $list = $database->getAuthorization()->skip(fn () => $database->find('realtime', [ + $list = Authorization::skip(fn () => $database->find('realtime', [ Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)), ])); @@ -463,13 +464,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) { $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId])); $consoleDatabase = getConsoleDB(); - $project = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); /** @var Appwrite\Utopia\Database\Documents\User $user */ $user = $database->getDocument('users', $userId); - $roles = $user->getRoles($database->getAuthorization()); + $roles = $user->getRoles(); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -525,7 +526,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); - $authorization = $app->getResource('authorization'); /* * Project Check @@ -537,7 +537,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -573,7 +573,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = $user->getRoles($authorization); + $roles = $user->getRoles(); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -586,8 +586,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $realtime->subscribe($project->getId(), $connection, $roles, $channels); - $realtime->connections[$connection]['authorization'] = $authorization; - $user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ @@ -616,7 +614,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $code = 500; } - $message = $th->getMessage(); // sanitize 0 && 5xx errors @@ -646,19 +643,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) { try { $response = new Response(new SwooleResponse()); - $projectId = $realtime->connections[$connection]['projectId'] ?? null; - - // Get authorization from connection (stored during onOpen) - $authorization = $realtime->connections[$connection]['authorization'] ?? null; - + $projectId = $realtime->connections[$connection]['projectId']; $database = getConsoleDB(); - $database->setAuthorization($authorization); if ($projectId !== 'console') { - $project = $authorization->skip(fn () => $database->getDocument('projects', $projectId)); - + $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); $database = getProjectDB($project); - $database->setAuthorization($authorization); } else { $project = null; } @@ -722,19 +712,10 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = $user->getRoles($database->getAuthorization()); + $roles = $user->getRoles(); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); - - // Preserve authorization before subscribe overwrites the connection array - $authorization = $realtime->connections[$connection]['authorization'] ?? null; - $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); - // Restore authorization after subscribe - if ($authorization !== null) { - $realtime->connections[$connection]['authorization'] = $authorization; - } - $user = $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ 'type' => 'response', diff --git a/app/worker.php b/app/worker.php index d31e63fc8b..3720fb85fe 100644 --- a/app/worker.php +++ b/app/worker.php @@ -49,30 +49,19 @@ use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; +Authorization::disable(); Runtime::enableCoroutine(); Server::setResource('register', fn () => $register); -Server::setResource('authorization', function () { - $authorization = new Authorization(); - $authorization->disable(); - return $authorization; -}, []); - -Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, Authorization $authorization) { +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); $adapter = new DatabasePool($pools->get('console')); $dbForPlatform = new Database($adapter, $cache); - - $dbForPlatform - ->setAuthorization($authorization) - ->setNamespace('_console') - ->setDocumentType('users', User::class) - ; - - + $dbForPlatform->setNamespace('_console'); + $dbForPlatform->setDocumentType('users', User::class); return $dbForPlatform; -}, ['cache', 'register', 'authorization']); +}, ['cache', 'register']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -85,7 +74,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform, Authorization $authorization) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -117,17 +106,15 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getSequence()); } - $database - ->setAuthorization($authorization) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform', 'authorization']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -141,7 +128,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - $database->setAuthorization($authorization); + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -178,17 +165,15 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf ->setNamespace('_' . $project->getSequence()); } - $database - ->setAuthorization($authorization) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; }; -}, ['pools', 'dbForPlatform', 'cache', 'authorization']); +}, ['pools', 'dbForPlatform', 'cache']); -Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { +Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { + return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -198,7 +183,6 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authoriza $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER) @@ -211,7 +195,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authoriza return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day @@ -530,8 +514,7 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->inject('authorization') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, Authorization $authorization) use ($worker, $queueName) { + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); if ($logger) { @@ -547,7 +530,7 @@ $worker $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', $authorization->getRoles()); + $log->addExtra('roles', Authorization::getRoles()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/composer.json b/composer.json index ef833cfb38..c2a3a965bd 100644 --- a/composer.json +++ b/composer.json @@ -45,14 +45,14 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.19.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "1.*", + "utopia-php/abuse": "1.*.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "2.*", + "utopia-php/audit": "2.0.2-rc3", "utopia-php/auth": "0.5.*", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", - "utopia-php/config": "1.*", - "utopia-php/database": "4.*", + "utopia-php/config": "1.*.*", + "utopia-php/database": "3.*.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.11.*", "utopia-php/emails": "0.6.*", @@ -64,7 +64,7 @@ "utopia-php/locale": "0.8.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.20.*", - "utopia-php/migration": "1.*", + "utopia-php/migration": "1.3.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 20b5c754eb..4b802b5611 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": "2d32f0fe31dc03c1f96a2582093afca1", + "content-hash": "0644a7889caffed39ba2c9c5189e45fe", "packages": [ { "name": "adhocore/jwt", @@ -3455,24 +3455,25 @@ }, { "name": "utopia-php/abuse", - "version": "1.0.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" + "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", - "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/3339d057c6bb1fa3e5ac5b2598923f6938425ec2", + "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2", "shasum": "" }, "require": { + "appwrite/appwrite": "19.*.*", "ext-curl": "*", "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "*" + "utopia-php/database": "3.*.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3500,9 +3501,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/1.0.2" + "source": "https://github.com/utopia-php/abuse/tree/1.2.0" }, - "time": "2025-10-20T07:18:33+00:00" + "time": "2026-01-05T21:29:10+00:00" }, { "name": "utopia-php/analytics", @@ -3552,23 +3553,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.3", + "version": "2.0.2-rc3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131" + "reference": "f60a298b516300f56a328403b334b7d62a96e7e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/662244bd170bab3ba45fd4470ac2e5a36c980131", - "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7", + "reference": "f60a298b516300f56a328403b334b7d62a96e7e7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "4.*", + "utopia-php/database": "3.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.2.*" + "utopia-php/validators": "0.1.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3595,9 +3596,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.3" + "source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3" }, - "time": "2026-01-13T09:49:40+00:00" + "time": "2026-01-06T15:32:52+00:00" }, { "name": "utopia-php/auth", @@ -3898,16 +3899,16 @@ }, { "name": "utopia-php/database", - "version": "4.4.0", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "783193d5cdc723b3784e8fb399068b17d4228d53" + "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/783193d5cdc723b3784e8fb399068b17d4228d53", - "reference": "783193d5cdc723b3784e8fb399068b17d4228d53", + "url": "https://api.github.com/repos/utopia-php/database/zipball/c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", + "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", "shasum": "" }, "require": { @@ -3950,9 +3951,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.4.0" + "source": "https://github.com/utopia-php/database/tree/3.6.1" }, - "time": "2026-01-08T04:54:39+00:00" + "time": "2025-12-16T09:55:41+00:00" }, { "name": "utopia-php/detector", @@ -4266,23 +4267,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.37", + "version": "0.33.36", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "30a119d76531d89da9240496940c84fcd9e1758b" + "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", - "reference": "30a119d76531d89da9240496940c84fcd9e1758b", + "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", + "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.2.*" + "utopia-php/validators": "0.1.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4308,9 +4309,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.37" + "source": "https://github.com/utopia-php/http/tree/0.33.36" }, - "time": "2026-01-13T10:10:21+00:00" + "time": "2026-01-12T07:32:29+00:00" }, { "name": "utopia-php/image", @@ -4515,16 +4516,16 @@ }, { "name": "utopia-php/migration", - "version": "1.4.3", + "version": "1.3.13", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" + "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", - "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/c5e3f5e970e62e8f7db97b5b90baae2af800a715", + "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715", "shasum": "" }, "require": { @@ -4533,7 +4534,7 @@ "ext-openssl": "*", "php": ">=8.1", "utopia-php/console": "0.0.*", - "utopia-php/database": "4.*", + "utopia-php/database": "3.*", "utopia-php/dsn": "0.2.*", "utopia-php/storage": "0.18.*" }, @@ -4564,9 +4565,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.4.3" + "source": "https://github.com/utopia-php/migration/tree/1.3.13" }, - "time": "2026-01-13T09:51:08+00:00" + "time": "2026-01-07T14:48:05+00:00" }, { "name": "utopia-php/mongo", @@ -5056,22 +5057,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.4", + "version": "0.8.6", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" + "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", + "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.*" + "utopia-php/framework": "0.33.36" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5101,9 +5102,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.4" + "source": "https://github.com/utopia-php/swoole/tree/0.8.6" }, - "time": "2025-09-07T09:39:46+00:00" + "time": "2026-01-12T07:57:35+00:00" }, { "name": "utopia-php/system", @@ -5213,16 +5214,16 @@ }, { "name": "utopia-php/validators", - "version": "0.2.0", + "version": "0.1.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" + "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", - "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", + "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", "shasum": "" }, "require": { @@ -5230,7 +5231,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "2.*", + "phpstan/phpstan": "1.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5252,9 +5253,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.2.0" + "source": "https://github.com/utopia-php/validators/tree/0.1.0" }, - "time": "2026-01-13T09:16:51+00:00" + "time": "2025-11-18T11:05:46+00:00" }, { "name": "utopia-php/vcs", @@ -8987,7 +8988,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/audit": 5 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -9011,5 +9014,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 8e098774e6..23dc6fc2e9 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -20,12 +20,10 @@ use Utopia\Database\Validator\Authorization; class TransactionState { private Database $dbForProject; - private Authorization $authorization; - /** @var Authorization $authorization */ - public function __construct(Database $dbForProject, Authorization $authorization) + + public function __construct(Database $dbForProject) { $this->dbForProject = $dbForProject; - $this->authorization = $authorization; } @@ -344,12 +342,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = $this->authorization->skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') { return []; } - $operations = $this->authorization->skip(fn () => $this->dbForProject->find('transactionLogs', [ + $operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index ea51225ba6..bc37924db6 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -100,6 +100,8 @@ abstract class Migration public function __construct() { + Authorization::disable(); + Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -127,7 +129,6 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -135,9 +136,6 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; - $authorization->disable(); - $authorization->setDefaultStatus(false); - return $this; } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index bf7d01764f..1ff2f8f706 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -21,7 +21,7 @@ class Action extends PlatformAction return \dirname(__DIR__, 6); } - protected function avatar(string $type, string $code, int $width, int $height, int $quality, Response $response): void + protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response): void { $code = \strtolower($code); $type = \strtolower($type); @@ -58,10 +58,10 @@ class Action extends PlatformAction unset($image); } - protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array + protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger): array { try { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -112,7 +112,7 @@ class Action extends PlatformAction ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - $authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); + Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -120,7 +120,7 @@ class Action extends PlatformAction do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php index 637ea647ef..04648752b5 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatar('browsers', $code, $width, $height, $quality, $response); + $this->avatarCallback('browsers', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index a6a013ef21..1c0de4001e 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -53,13 +53,12 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -69,7 +68,7 @@ class Get extends Action $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index f8e7a35b05..9d53991dd6 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -53,13 +53,12 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -70,7 +69,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index 37776a3466..f7c983db78 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -53,13 +53,12 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -74,7 +73,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php index 87357f14c7..5d3429b377 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatar('credit-cards', $code, $width, $height, $quality, $response); + $this->avatarCallback('credit-cards', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php index 8230b15f50..c3960c134e 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatar('flags', $code, $width, $height, $quality, $response); + $this->avatarCallback('flags', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 33b69dd589..47afc90986 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -13,7 +13,6 @@ 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\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; @@ -143,7 +142,7 @@ class Base extends Action return $deployment; } - public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = ''): Document + public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document { $deploymentId = ID::unique(); $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); @@ -240,7 +239,7 @@ class Base extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -266,7 +265,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -303,7 +302,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -329,8 +328,6 @@ class Base extends Action } } - $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); - $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) @@ -339,34 +336,4 @@ class Base extends Action return $deployment; } - - /** - * Update empty manual rule for deployment. - * In case of first deployment, deployment ID will be empty in the rules, so we need to update it here. - * - * @param \Utopia\Database\Document $project - * @param \Utopia\Database\Document $resource - * @param \Utopia\Database\Document $deployment - * @param \Utopia\Database\Database $dbForPlatform - * @return void - */ - public static function updateEmptyManualRule(Document $project, Document $resource, Document $deployment, Database $dbForPlatform, Authorization $authorization) - { - $resourceType = $resource->getCollection() === 'sites' ? 'site' : 'function'; - - $queries = [ - Query::equal('projectInternalId', [$project->getSequence()]), - Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), - Query::equal('deploymentResourceType', [$resourceType]), - Query::equal('deploymentId', ['']), - Query::equal('type', ['deployment']), - Query::equal('trigger', ['manual']), - ]; - $dbForPlatform->forEach('rules', function (Document $rule) use ($deployment, $dbForPlatform, $authorization) { - $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([ - 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), - ]))); - }, $queries); - } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 1468bf71ac..aa43b12125 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -60,7 +60,6 @@ class Get extends Action ->inject('response') ->inject('dbForPlatform') ->inject('platform') - ->inject('authorization') ->callback($this->action(...)); } @@ -69,8 +68,7 @@ class Get extends Action string $type, Response $response, Database $dbForPlatform, - array $platform, - Authorization $authorization, + array $platform ) { $domains = $platform['hostnames'] ?? []; if ($type === 'rules') { @@ -123,7 +121,7 @@ class Get extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $document = $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ + $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$value]), ])); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index e2df5d92e6..83a401a35e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -292,7 +292,7 @@ abstract class Action extends UtopiaAction }; } - protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): Document + protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document { $key = $attribute->getAttribute('key'); $type = $attribute->getAttribute('type', ''); @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException(), params: [$type]); } - $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, params: [$databaseId]); @@ -371,7 +371,7 @@ abstract class Action extends UtopiaAction \in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) && $attribute->getAttribute('required') ) { - $hasData = !$authorization->skip(fn () => $dbForProject + $hasData = !Authorization::skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -472,9 +472,9 @@ abstract class Action extends UtopiaAction return $attribute; } - protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document + protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index 442461fdd3..f04532aeee 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,11 +69,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -83,7 +81,7 @@ class Create extends Action 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 92324aae70..003b4227c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,11 +68,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -81,7 +79,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_BOOLEAN, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index bd3108a871..c2982445a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute( $databaseId, @@ -92,8 +90,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index 2518875424..984d4b0245 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_DATETIME, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 37ae2a7bfe..649cde10aa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -67,13 +67,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index a36e264e50..b36072eb75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute( $databaseId, @@ -92,8 +90,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 609a337625..382f16b469 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_EMAIL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 3c47d1fdfe..9145191b0c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,11 +73,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { if (!is_null($default) && !\in_array($default, $elements, true)) { throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); @@ -100,8 +98,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 5bea5230c0..2f47eb0cc6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,11 +71,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -84,7 +82,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_ENUM, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 0dc11bd76c..56d8874794 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -75,11 +74,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $min ??= -PHP_FLOAT_MAX; $max ??= PHP_FLOAT_MAX; @@ -102,7 +100,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 20b5c0767d..330c649f27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,11 +71,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -84,7 +82,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_FLOAT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 436b22c6c9..3a8eece531 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -68,13 +68,12 @@ class Get extends Action ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 2adf3977f4..2340d1d55d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute( $databaseId, @@ -92,8 +90,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index eccf18b005..236dbf7f83 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_IP, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 58ded9b78a..30f58097ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -75,11 +74,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $min ??= \PHP_INT_MIN; $max ??= \PHP_INT_MAX; @@ -104,7 +102,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 84a43018d1..67c371c69d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,11 +71,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -84,7 +82,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_INTEGER, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index fc846957b0..f0fd728902 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,18 +69,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_LINESTRING, 'required' => $required, 'default' => $default - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 8fff545921..3407da2b34 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_LINESTRING, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index a89c21581d..f2e4d19267 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,18 +69,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POINT, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index 9561fe6b96..86e78e56e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_POINT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 54da3ac604..4c49b21050 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,18 +69,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POLYGON, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index b82a3d4be0..0dbb117cec 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_POLYGON, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index 615e64dfd7..b43568a968 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -83,17 +83,16 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $key ??= $relatedCollectionId; $twoWayKeyWasProvided = $twoWayKey !== null; $twoWayKey ??= $collectionId; - $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, params: [$databaseId]); } @@ -155,7 +154,7 @@ class Create extends Action 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, ] - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); foreach ($attribute->getAttribute('options', []) as $k => $option) { $attribute->setAttribute($k, $option); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index d180131a44..feed58a4ff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,7 +71,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -84,8 +82,7 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -93,7 +90,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_RELATIONSHIP, required: false, options: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index b3fe03cace..b42558f063 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -14,7 +14,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -78,7 +77,6 @@ class Create extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -95,8 +93,7 @@ class Create extends Action Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, - array $plan, - Authorization $authorization + array $plan ): void { if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.'); @@ -135,8 +132,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $attribute->setAttribute('encrypt', $encrypt); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 37547f3da8..53ea2a0e03 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -73,7 +72,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -87,8 +85,7 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -96,7 +93,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, size: $size, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index ed1a23acf5..7529845016 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,7 +70,6 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -85,8 +83,7 @@ class Create extends Action UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -96,7 +93,7 @@ class Create extends Action 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 08f7a26fd9..9ba8ebb859 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,7 +69,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -83,8 +81,7 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->updateAttribute( $databaseId, @@ -92,7 +89,6 @@ class Update extends Action $key, $dbForProject, $queueForEvents, - $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_URL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 61c5b295cf..6bfe5f8913 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -64,13 +64,12 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 89cc14056a..724f40f00e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -85,13 +85,12 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index fd2c419954..af36649061 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -64,13 +64,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index ec65135a05..f16d00998d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -258,9 +258,9 @@ abstract class Action extends DatabasesAction Document $collection, Document $document, Database $dbForProject, + /* options */ array &$collectionsCache, - Authorization $authorization, ?int &$operations = null, ): bool { @@ -297,7 +297,7 @@ abstract class Action extends DatabasesAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = $authorization->skip( + $relatedCollectionDoc = Authorization::skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId @@ -323,8 +323,7 @@ abstract class Action extends DatabasesAction document: $relation, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations, - authorization: $authorization + operations: $operations ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 16b7bd1b25..53831f0fc5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -85,21 +85,20 @@ class Decrement extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $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, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -107,7 +106,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index 7adae7633b..ea680db3b1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -85,21 +85,20 @@ class Increment extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $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, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -107,7 +106,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index bbc63da499..6ec06f5c8a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -24,7 +24,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -133,10 +132,9 @@ class Create extends Action ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $data = \is_string($data) ? \json_decode($data, true) @@ -180,19 +178,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -206,7 +204,7 @@ class Create extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext()); } - $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) { + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, @@ -249,8 +247,8 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')'); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); } } } @@ -261,25 +259,21 @@ class Create extends Action $operations = 0; - $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations, $authorization) { + $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations) { $operations++; $documentSecurity = $collection->getAttribute('documentSecurity', false); + $validator = new Authorization($permission); - $validCollection = $authorization->isValid( - new Input($permission, $collection->getPermissionsByType($permission)) - ); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $valid = $validator->isValid($collection->getPermissionsByType($permission)); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($permission === Database::PERMISSION_UPDATE) { - $validDocument = $authorization->isValid( - new Input($permission, $document->getUpdate()) - ); - $valid = $validCollection || $validDocument; + $valid = $valid || $validator->isValid($document->getUpdate()); if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } } @@ -304,7 +298,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization->skip( + $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -320,7 +314,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = $authorization->skip( + $current = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -375,7 +369,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -474,7 +468,6 @@ class Create extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 7acf8e386e..faae638c88 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -83,7 +83,6 @@ class Delete extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -98,19 +97,18 @@ class Delete extends Action Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, - array $plan, - Authorization $authorization + array $plan ): void { - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -123,7 +121,7 @@ class Delete extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -133,7 +131,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -207,7 +205,6 @@ class Delete extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization ); $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index cb8b0dd42e..f560267d4b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -70,21 +70,20 @@ class Get extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -126,7 +125,6 @@ class Get extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization, operations: $operations ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index 2f5579f0ca..a4dd38ef67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -72,14 +72,13 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index a92d8ec180..707857347a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -87,11 +87,10 @@ class Update extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -99,16 +98,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -126,7 +125,7 @@ class Update extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -141,7 +140,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -154,7 +153,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -172,7 +171,7 @@ class Update extends Action $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { $operations++; $relationships = \array_filter( @@ -196,7 +195,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization->skip( + $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -213,7 +212,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -250,7 +249,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -341,7 +340,6 @@ class Update extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization, ); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index 62e59dd010..b32871add2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -91,11 +91,10 @@ class Upsert extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -107,15 +106,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -140,7 +139,7 @@ class Upsert extends Action // Use transaction-aware document retrieval to see changes from same transaction $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -156,7 +155,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -169,7 +168,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -182,7 +181,7 @@ class Upsert extends Action $newDocument = new Document($data); $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { $operations++; $relationships = \array_filter( @@ -206,7 +205,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization->skip( + $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -223,7 +222,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -260,7 +259,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -362,7 +361,6 @@ class Upsert extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization ); $relationships = \array_map( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index ff94e67b02..8b770284c3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -74,21 +74,20 @@ class XList extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -116,7 +115,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); @@ -162,8 +161,7 @@ class XList extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization, - operations: $operations + operations: $operations, ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index d8df8f1f8c..e7909772a5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -57,13 +57,12 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 5b035a8688..872b7348fe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -79,13 +79,12 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index d9f9f66504..27b28e866c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -70,13 +70,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index 661f259910..d66bf8f38f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -59,13 +59,12 @@ class Get extends Action ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 90826ffbe3..abbdefb4d5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -66,14 +66,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { /** @var Document $database */ - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); @@ -113,7 +112,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 0b6e47a798..0f5a57c6e9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -71,14 +71,13 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void { - $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, params: [$databaseId]); @@ -113,9 +112,9 @@ class XList extends Action $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - $os = $detector->getOS() ?: []; - $client = $detector->getClient() ?: []; - $device = $detector->getDevice() ?: []; + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); $output[$i] = new Document([ 'event' => $log['event'], @@ -123,20 +122,20 @@ class XList extends Action 'userEmail' => $log['data']['userEmail'] ?? null, 'userName' => $log['data']['userName'] ?? null, 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'] ?? null, - 'time' => $log['time'] ?? null, - 'osCode' => $os['osCode'] ?? null, - 'osName' => $os['osName'] ?? null, - 'osVersion' => $os['osVersion'] ?? null, - 'clientType' => $client['clientType'] ?? null, - 'clientCode' => $client['clientCode'] ?? null, - 'clientName' => $client['clientName'] ?? null, - 'clientVersion' => $client['clientVersion'] ?? null, - 'clientEngine' => $client['clientEngine'] ?? null, - 'clientEngineVersion' => $client['clientEngineVersion'] ?? null, - 'deviceName' => $device['deviceName'] ?? null, - 'deviceBrand' => $device['deviceBrand'] ?? null, - 'deviceModel' => $device['deviceModel'] ?? null + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index 304ce5c88e..e319a33e67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -71,13 +71,12 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index 0552a31509..c4a46650c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -63,11 +63,10 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { $database = $dbForProject->getDocument('databases', $databaseId); $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); @@ -84,7 +83,7 @@ class Get extends Action str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index c23286f3cd..b0b0385bf5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -67,13 +67,12 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php index 4ca20f8414..20c71223c6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -55,11 +55,10 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('user') - ->inject('authorization') ->callback($this->action(...)); } - public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, Authorization $authorization): void + public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user): void { $permissions = []; if (!empty($user->getId())) { @@ -74,7 +73,7 @@ class Create extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->createDocument('transactions', new Document([ + $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ '$id' => ID::unique(), '$permissions' => $permissions, 'status' => 'pending', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php index f09ed2bc27..5a2568db0c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -18,7 +18,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -64,22 +63,21 @@ class Create extends Action ->inject('dbForProject') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization): void + public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan): void { if (empty($operations)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -115,13 +113,13 @@ class Create extends Action throw new Exception(Exception::USER_UNAUTHORIZED); } - $database = $databases[$operation['databaseId']] ??= $authorization->skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); + $database = $databases[$operation['databaseId']] ??= Authorization::skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$operation['databaseId']]); } $collection = $collections[$operation[$this->getGroupId()]] ??= - $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND, params: [$operation[$this->getGroupId()]]); @@ -167,20 +165,14 @@ class Create extends Action // For individual operations, enforce permissions unless using API key/admin if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - - $collectionValid = $authorization->isValid( - new Input($permissionType, $collection->getPermissionsByType($permissionType)) - ); + $validator = new Authorization($permissionType); + $collectionValid = $validator->isValid($collection->getPermissionsByType($permissionType)); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $authorization->isValid( - new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) - ); + $documentValid = $validator->isValid($document->getUpdate()); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $authorization->isValid( - new Input(Database::PERMISSION_DELETE, $document->getDelete()) - ); + $documentValid = $validator->isValid($document->getDelete()); } } @@ -197,7 +189,7 @@ class Create extends Action // Users can only set permissions for roles they have if (isset($operation['data']['$permissions'])) { $permissions = $operation['data']['$permissions']; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -209,7 +201,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -238,7 +230,7 @@ class Create extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { $dbForProject->createDocuments('transactionLogs', $staged); return $dbForProject->increaseDocumentAttribute( 'transactions', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php index e4f1051464..9235c81b8e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -76,7 +76,6 @@ class Update extends Action ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') - ->inject('authorization') ->callback($this->action(...)); } @@ -103,7 +102,7 @@ class Update extends Action * @throws Structure * @throws \Utopia\Exception */ - public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization): void + public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void { if (!$commit && !$rollback) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); @@ -112,11 +111,11 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -139,12 +138,12 @@ class Update extends Action $currentDocumentId = null; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -168,7 +167,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = $authorization->skip( + $collections[$collectionId] = Authorization::skip( fn () => $dbForProject->getCollection($collectionId) ); } @@ -233,7 +232,7 @@ class Update extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -244,33 +243,33 @@ class Update extends Action ->setDocument($transaction); }); } catch (NotFoundException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e, params: [$currentDocumentId ?? 'unknown']); } catch (DuplicateException | ConflictException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_CONFLICT, previous: $e); } catch (StructureException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (LimitException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, $e->getMessage()); } catch (TransactionException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_FAILED, $e->getMessage()); } catch (QueryException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); @@ -298,11 +297,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = $authorization->skip(fn () => $dbForProject->findOne('databases', [ + $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = $authorization->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -394,7 +393,7 @@ class Update extends Action } if ($rollback) { - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'failed']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index a1aa7a70b8..a717b00ae4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -59,11 +59,10 @@ class Get extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void { $database = $dbForProject->getDocument('databases', $databaseId); @@ -82,7 +81,7 @@ class Get extends Action str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 757f845c68..c13149cfc7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -56,11 +56,10 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $range, UtopiaResponse $response, Database $dbForProject): void { $periods = Config::getParam('usage', []); @@ -75,7 +74,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php index eede1b221b..c0d502d10a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php @@ -60,7 +60,6 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php index cd8d392cfc..c5939b6974 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php @@ -61,7 +61,6 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php index 79722efee1..63693abb67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php @@ -62,7 +62,6 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php index c39681a743..b022d0ed85 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php @@ -63,7 +63,6 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php index da63b0cef7..8a691a6e98 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php @@ -58,7 +58,6 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php index 51e7f295a1..6d19f99b7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php @@ -61,7 +61,6 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php index daca13d587..48a04304bd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php @@ -62,7 +62,6 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php index 4d5881c81e..bd280a2910 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php @@ -64,7 +64,6 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php index 122671adc5..ac5c1cf907 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php @@ -65,7 +65,6 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php index cd898fa0bf..8293d66992 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php @@ -63,7 +63,6 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php index ee9c5f6cb1..bf2815db45 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php @@ -64,7 +64,6 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php index 39dafbd1a6..ee88ac8683 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php @@ -61,7 +61,6 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php index 80c764b4c5..9b38cd9dfd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php @@ -61,7 +61,6 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php index 54ed029c71..7db8625ebf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php @@ -62,7 +62,6 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index 45e0cc6f60..e0ed059681 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -63,7 +63,6 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index f1f4ebb4a9..7afc239201 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -64,7 +64,6 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php index 227fece7de..6110d6ee07 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php @@ -61,7 +61,6 @@ class Create extends LineCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php index b0e433da5f..afd0098152 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php @@ -63,7 +63,6 @@ class Update extends LineUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php index 3fc5865905..084adca860 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php @@ -61,7 +61,6 @@ class Create extends PointCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 040b8171d7..632be85871 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php @@ -63,7 +63,6 @@ class Update extends PointUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php index 630340ba7b..723940af58 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php @@ -61,7 +61,6 @@ class Create extends PolygonCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 43b4a4e6a4..91b55f74b4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php @@ -63,7 +63,6 @@ class Update extends PolygonUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php index 7f28a3cdb7..f3933160c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php @@ -73,7 +73,6 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index fd7fdab8de..eb87713457 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php @@ -65,7 +65,6 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php index ff50313a7c..9279409e88 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php @@ -66,7 +66,6 @@ class Create extends StringCreate ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 6ad1be124b..9fffa71b33 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php @@ -65,7 +65,6 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php index b19d6e80a2..50f5ea5d5b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php @@ -61,7 +61,6 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index dce11964e8..b52ea66ce1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php @@ -62,7 +62,6 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 13ebe14682..39551e5113 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -52,7 +52,6 @@ class XList extends AttributesXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php index bd08ad5617..7287c2cb3e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -67,7 +67,6 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php index 925a7b2494..d4af8b3508 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php @@ -55,7 +55,6 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php index ad83291815..4286ee07ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php @@ -50,7 +50,6 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index 09720f4d71..727334b6da 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php @@ -66,8 +66,6 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php index 7fa8073d1e..7d187ab5a1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php @@ -61,7 +61,6 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php index 246d569825..75ee507aa8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php @@ -52,7 +52,6 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index 1dc2d3ea43..bf5f27e388 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -54,7 +54,6 @@ class XList extends IndexXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php index 79691436e4..5eab050b7e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php @@ -50,7 +50,6 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php index b9896d282d..accb0392fe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php @@ -66,7 +66,6 @@ class Delete extends DocumentsDelete ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php index f4ccea1698..fea59b8b13 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php @@ -68,7 +68,6 @@ class Update extends DocumentsUpdate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php index 69a687d92f..492af25e9f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php @@ -68,7 +68,6 @@ class Upsert extends DocumentsUpsert ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php index a660b008e1..42f2919ce1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php @@ -67,7 +67,6 @@ class Decrement extends DecrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php index c2b69429ce..3d04d71c26 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php @@ -67,7 +67,6 @@ class Increment extends IncrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php index c70ed71378..b5491a593b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php @@ -111,7 +111,6 @@ class Create extends DocumentCreate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php index 1763491c19..bcd8682a48 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php @@ -70,7 +70,6 @@ class Delete extends DocumentDelete ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php index bb24e93de0..450fb4d746 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php @@ -58,7 +58,6 @@ class Get extends DocumentGet ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php index 86bfcfec85..27bd82195d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php @@ -51,7 +51,6 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php index 0879055a78..fe4ffc4995 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php @@ -69,7 +69,6 @@ class Update extends DocumentUpdate ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index 99e0487c93..0fbaa921cb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -72,7 +72,6 @@ class Upsert extends DocumentUpsert ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 230d391110..c51017fa75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -59,7 +59,6 @@ class XList extends DocumentXList ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php index 0d3bc9afc1..03316783cd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -62,7 +62,6 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php index b8be7edd56..0fb44ee94a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php @@ -52,7 +52,6 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index 5532203d0a..e0c590379b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -55,7 +55,6 @@ class XList extends CollectionXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php index e7e5f0132f..27454664f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php @@ -50,7 +50,6 @@ class Create extends TransactionsCreate ->inject('response') ->inject('dbForProject') ->inject('user') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php index 1228c83e30..4668ae2d15 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php @@ -54,7 +54,6 @@ class Create extends OperationsCreate ->inject('dbForProject') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php index 8be28ce9f7..4337a8d28d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php @@ -60,7 +60,6 @@ class Update extends TransactionsUpdate ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php index 87be8a9eab..89b9fbd8c2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php @@ -48,7 +48,6 @@ class Get extends DatabaseUsageGet ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php index 2cde337f5f..0bd96fc40a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php @@ -46,7 +46,6 @@ class XList extends DatabaseUsageXList ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index c5ae08728d..e7e34d4c5b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -17,7 +17,6 @@ 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\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -89,7 +88,6 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -107,8 +105,7 @@ class Create extends Action Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, - array $plan, - Authorization $authorization + array $plan ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index acfaa965ac..0aaea3bd4a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -78,7 +77,6 @@ class Create extends Base ->inject('project') ->inject('queueForBuilds') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -97,8 +95,7 @@ class Create extends Base Event $queueForEvents, Document $project, Build $queueForBuilds, - GitHub $github, - Authorization $authorization + GitHub $github ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -130,9 +127,7 @@ class Create extends Base queueForBuilds: $queueForBuilds, template: $template, github: $github, - activate: $activate, - referenceType: $type, - reference: $reference + activate: $activate ); $queueForEvents @@ -175,9 +170,6 @@ class Create extends Base ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); - - $this->updateEmptyManualRule($project, $function, $deployment, $dbForPlatform, $authorization); - $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php index 25dce63b38..69594c3d86 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -87,7 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github, + GitHub $github ) { $function = $dbForProject->getDocument('functions', $functionId); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 1a265298d3..81f55ba829 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -29,7 +29,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -100,7 +99,6 @@ class Create extends Base ->inject('proofForToken') ->inject('executor') ->inject('platform') - ->inject('authorization') ->callback($this->action(...)); } @@ -125,8 +123,7 @@ class Create extends Base Store $store, Token $proofForToken, Executor $executor, - array $platform, - Authorization $authorization, + array $platform ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -164,10 +161,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -183,7 +180,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); @@ -197,8 +194,10 @@ class Create extends Base throw new Exception(Exception::BUILD_NOT_READY); } - if (!$authorization->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization('execute'); + + if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } $jwt = ''; // initialize @@ -296,7 +295,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -337,7 +336,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -489,7 +488,7 @@ class Create extends Base ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; - $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index c7a9a6d330..9a93e5a342 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -61,7 +61,6 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -71,8 +70,7 @@ class Delete extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -110,7 +108,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index c5eebe139e..6bd0a3675e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -52,7 +52,6 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -60,13 +59,12 @@ class Get extends Base string $functionId, string $executionId, Response $response, - Database $dbForProject, - Authorization $authorization + Database $dbForProject ) { - $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index ff381e1f3d..20680e87ff 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -60,7 +60,6 @@ class XList extends Base ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -69,13 +68,12 @@ class XList extends Base array $queries, bool $includeTotal, Response $response, - Database $dbForProject, - Authorization $authorization + Database $dbForProject ) { - $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index 6ad488283e..5c226c5925 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -115,7 +115,6 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -153,8 +152,7 @@ class Create extends Base Func $queueForFunctions, Database $dbForPlatform, Request $request, - GitHub $github, - Authorization $authorization + GitHub $github ) { // Temporary abuse check @@ -239,7 +237,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = $authorization->skip( + $schedule = Authorization::skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -317,7 +315,6 @@ class Create extends Base template: $template, github: $github, activate: true, - authorization: $authorization, reference: $providerBranch, referenceType: 'branch' ); @@ -369,7 +366,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $rule = $authorization->skip( + $rule = Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index 9cafc17bbe..dfa6636554 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -61,7 +61,6 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -71,8 +70,7 @@ class Delete extends Base Database $dbForProject, DeleteEvent $queueForDeletes, Event $queueForEvents, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -89,7 +87,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index aeccf98a02..b6dcfd6cf8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -62,7 +62,6 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -73,8 +72,7 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -103,7 +101,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -114,12 +112,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { + Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index 55c5b30418..adb29bc533 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -104,7 +104,6 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') - ->inject('authorization') ->callback($this->action(...)); } @@ -135,8 +134,7 @@ class Update extends Base Build $queueForBuilds, Database $dbForPlatform, GitHub $github, - Executor $executor, - Authorization $authorization + Executor $executor ) { // TODO: If only branch changes, re-deploy $function = $dbForProject->getDocument('functions', $functionId); @@ -284,7 +282,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents->setParam('functionId', $function->getId()); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index 1fa65d0cc9..acb6995d6f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -55,11 +55,10 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $functionId, string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $functionId, string $range, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); @@ -84,7 +83,7 @@ class Get extends Base str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index 38a95d4469..6a4ded4db7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -52,11 +52,10 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -76,7 +75,7 @@ class XList extends Base str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 5438479d40..815f1bd8fc 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -65,7 +65,6 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') - ->inject('authorization') ->callback($this->action(...)); } @@ -77,8 +76,7 @@ class Create extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Document $project, - Authorization $authorization + Document $project ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -121,7 +119,7 @@ class Create extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 161eed3112..50c1de4232 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -57,7 +57,6 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -66,8 +65,7 @@ class Delete extends Base string $variableId, Response $response, Database $dbForProject, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -94,7 +92,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 6af5ac90c2..5c1f5809cd 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -62,7 +62,6 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -74,8 +73,7 @@ class Update extends Base ?bool $secret, Response $response, Database $dbForProject, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -112,7 +110,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index ac1fee6bad..285f78319a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -25,6 +25,7 @@ use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Detector\Detection\Rendering\SSR; use Utopia\Detector\Detection\Rendering\XStatic; use Utopia\Detector\Detector\Rendering; @@ -1115,7 +1116,7 @@ class Builds extends Action ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $resource->getAttribute('schedule')) ->setAttribute('active', !empty($resource->getAttribute('schedule')) && !empty($resource->getAttribute('deploymentId'))); - $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } Console::info('Deployment action finished'); @@ -1324,6 +1325,7 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception + * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1412,11 +1414,11 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = $dbForPlatform->findOne('rules', [ + $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal("deploymentInternalId", [$deployment->getSequence()]), - ]); + ])); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $previewUrl = match($resource->getCollection()) { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 3de0322d6e..4ba51bca37 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -87,7 +87,6 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -107,8 +106,7 @@ class Create extends Action Device $deviceForSites, Device $deviceForLocal, Build $queueForBuilds, - array $plan, - Authorization $authorization + array $plan ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -278,7 +276,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -343,7 +341,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -368,8 +366,6 @@ class Create extends Action } } - - $metadata = null; $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 9554e2aa14..2f9b1bdfde 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -65,7 +65,6 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') - ->inject('authorization') ->callback($this->action(...)); } @@ -79,8 +78,7 @@ class Create extends Action Database $dbForPlatform, Event $queueForEvents, Build $queueForBuilds, - Device $deviceForSites, - Authorization $authorization + Device $deviceForSites ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -149,7 +147,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 30d5e779c1..5f1d446809 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -79,7 +79,6 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -98,8 +97,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github, - Authorization $authorization + GitHub $github ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -132,7 +130,6 @@ class Create extends Base template: $template, github: $github, activate: $activate, - authorization: $authorization, ); $queueForEvents @@ -192,7 +189,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -212,8 +209,6 @@ class Create extends Base ])) ); - $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); - $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index feff28427e..915e3c5c9f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -73,7 +72,6 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -89,8 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github, - Authorization $authorization + GitHub $github ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -113,7 +110,6 @@ class Create extends Base template: $template, github: $github, activate: $activate, - authorization: $authorization, reference: $reference, referenceType: $type ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index b5d956128b..f962d0118d 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -60,7 +60,6 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -71,8 +70,7 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $site = $dbForProject->getDocument('sites', $siteId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -106,12 +104,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { + Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index 5c274d6a20..af96c10457 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -55,7 +55,6 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -63,8 +62,7 @@ class Get extends Base string $siteId, string $range, Response $response, - Database $dbForProject, - Authorization $authorization + Database $dbForProject ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -93,7 +91,7 @@ class Get extends Base ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index a90cb0cab9..d36cc56ae5 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -52,11 +52,10 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -79,7 +78,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index 4757461a98..ed5c23b6c1 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -22,7 +22,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -91,7 +90,6 @@ class Create extends Action ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->inject('authorization') ->callback($this->action(...)); } @@ -107,26 +105,26 @@ class Create extends Action Event $queueForEvents, string $mode, Device $deviceForFiles, - Device $deviceForLocal, - Authorization $authorization + Device $deviceForLocal ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $allowedPermissions = [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, + \Utopia\Database\Database::PERMISSION_READ, + \Utopia\Database\Database::PERMISSION_UPDATE, + \Utopia\Database\Database::PERMISSION_DELETE, ]; // Map aggregate permissions to into the set of individual permissions they represent. @@ -143,7 +141,7 @@ class Create extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!$isAPIKey && !$isPrivilegedUser) { foreach (\Utopia\Database\Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -156,7 +154,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -381,10 +379,11 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } // Trigger after create success hook @@ -428,12 +427,13 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } try { - $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index ca376842e2..eccacaafd2 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -14,7 +14,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -65,7 +64,6 @@ class Delete extends Action ->inject('queueForEvents') ->inject('deviceForFiles') ->inject('queueForDeletes') - ->inject('authorization') ->callback($this->action(...)); } @@ -77,33 +75,33 @@ class Delete extends Action Event $queueForEvents, Device $deviceForFiles, DeleteEvent $queueForDeletes, - Authorization $authorization ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); + $validator = new Authorization(Database::PERMISSION_DELETE); + $valid = $validator->isValid($bucket->getDelete()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for delete - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $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 && !$authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $deviceDeleted = false; @@ -127,7 +125,7 @@ class Delete extends Action if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = $authorization->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index bbceff51ec..45e3b83375 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -14,7 +14,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -69,7 +68,6 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->inject('authorization') ->callback($this->action(...)); } @@ -82,14 +80,13 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles, - Authorization $authorization, + Device $deviceForFiles ) { /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -97,16 +94,17 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index caaab29efc..77f163e5fb 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -10,7 +10,6 @@ use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -50,7 +49,6 @@ class Get extends Action ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -59,27 +57,27 @@ class Get extends Action string $fileId, Response $response, Database $dbForProject, - Authorization $authorization ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 7ab3e713bc..9c4e49d0bb 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -17,7 +17,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Image\Image; use Utopia\Platform\Action; @@ -91,7 +90,6 @@ class Get extends Action ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') - ->inject('authorization') ->callback($this->action(...)); } @@ -116,8 +114,7 @@ class Get extends Action Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, - Document $project, - Authorization $authorization + Document $project ) { if (!\extension_loaded('imagick')) { @@ -125,10 +122,10 @@ class Get extends Action } /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -140,16 +137,17 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -271,11 +269,11 @@ class Get extends Action $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!User::isPrivileged($authorization->getRoles())) { + if (!User::isPrivileged(Authorization::getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php index 516343e23f..67372435b1 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php @@ -51,7 +51,6 @@ class Get extends Action ->inject('project') ->inject('mode') ->inject('deviceForFiles') - ->inject('authorization') ->callback($this->action(...)); } @@ -65,8 +64,7 @@ class Get extends Action Database $dbForPlatform, Document $project, string $mode, - Device $deviceForFiles, - Authorization $authorization + Device $deviceForFiles ) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -88,15 +86,15 @@ class Get extends Action $disposition = $decoded['disposition'] ?? 'inline'; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index 57856c1564..be78cc358b 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -14,7 +14,6 @@ use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -63,7 +62,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -74,26 +72,26 @@ class Update extends Action ?array $permissions, Response $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $validator = new Authorization(Database::PERMISSION_UPDATE); + $valid = $validator->isValid($bucket->getUpdate()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for update - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -107,7 +105,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -120,7 +118,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -141,7 +139,7 @@ class Update extends Action if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index 3874fedacf..41ee95b165 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -15,7 +15,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -70,7 +69,6 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->inject('authorization') ->callback($this->action(...)); } @@ -83,14 +81,13 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles, - Authorization $authorization + Device $deviceForFiles ) { /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -98,16 +95,17 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index 3663b56fab..e46fdb2a0a 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -16,7 +16,6 @@ use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -62,7 +61,6 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('mode') - ->inject('authorization') ->callback($this->action(...)); } @@ -73,22 +71,22 @@ class XList extends Action bool $includeTotal, Response $response, Database $dbForProject, - string $mode, - Authorization $authorization + string $mode ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } try { @@ -121,7 +119,7 @@ class XList extends Action if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -138,8 +136,8 @@ class XList extends Action $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; } else { - $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $includeTotal ? $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $includeTotal ? Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php index 4e75de27c8..5c3515122b 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php @@ -51,7 +51,6 @@ class Get extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') - ->inject('authorization') ->callback($this->action(...)); } @@ -60,8 +59,7 @@ class Get extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB, - Authorization $authorization, + callable $getLogsDB ): void { $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -77,20 +75,19 @@ class Get extends Action $statsDocId = md5('_inf_' . $metric); - $totalSize = 0; - - try { - $dbForLogs = $getLogsDB($project); - $storageStats = $authorization->skip(fn () => $dbForLogs->getDocument( + $dbForLogs = call_user_func($getLogsDB, $project); + $storageStats = Authorization::skip( + fn () => $dbForLogs->getDocument( 'stats', $statsDocId, [Query::select(['value'])] - )); + ) + ); - $totalSize = $storageStats->getAttribute('value', 0); - } catch (\Throwable) { - // Stats may not be available, default to 0 - } + /** + * The value can be 0 if stats were not aggregated when this request was made! + */ + $totalSize = $storageStats->isEmpty() ? 0 : $storageStats->getAttribute('value', 0); $bucket->setAttribute('totalSize', $totalSize); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php index 601d9b5321..a2c880ce08 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php @@ -58,7 +58,6 @@ class XList extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') - ->inject('authorization') ->callback($this->action(...)); } @@ -69,8 +68,7 @@ class XList extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB, - Authorization $authorization + callable $getLogsDB ) { try { $queries = Query::parseQueries($queries); @@ -119,6 +117,7 @@ class XList extends Action if (!empty($buckets)) { $bucketByStatsId = []; + $dbForLogs = call_user_func($getLogsDB, $project); foreach ($buckets as $bucket) { $metric = str_replace( @@ -135,28 +134,22 @@ class XList extends Action $bucket->setAttribute('totalSize', 0); } - try { - $dbForLogs = $getLogsDB($project); + /* @type Document[] $stats */ + $stats = Authorization::skip(function () use ($dbForLogs, $bucketByStatsId) { + $statsIds = array_keys($bucketByStatsId); - /* @var array $stats */ - $stats = $authorization->skip(function () use ($dbForLogs, $bucketByStatsId) { - $statsIds = array_keys($bucketByStatsId); + return $dbForLogs->find('stats', [ + Query::equal('$id', $statsIds), + Query::select(['value']), + ]); + }); - return $dbForLogs->find('stats', [ - Query::equal('$id', $statsIds), - Query::select(['value']), - ]); - }); + foreach ($stats as $stat) { + $bucket = $bucketByStatsId[$stat->getId()]; - foreach ($stats as $stat) { - $bucket = $bucketByStatsId[$stat->getId()]; - - if ($bucket) { - $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); - } + if ($bucket) { + $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); } - } catch (\Throwable) { - // Stats may not be available, default to 0 } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php index a7bda355da..b816e83f72 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php @@ -54,11 +54,10 @@ class Get extends Action ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, Authorization $authorization) + public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) { $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -76,7 +75,7 @@ class Get extends Action str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - $authorization->skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php index 44fdd54e8c..d29fa7c1b4 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php @@ -49,11 +49,10 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -64,7 +63,7 @@ class XList extends Action METRIC_FILES_STORAGE, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index 5f1bd55788..f79dece530 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -6,31 +6,32 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Documents\User; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; class Action extends UtopiaAction { - protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, string $bucketId, string $fileId): array + protected function getFileAndBucket(Database $dbForProject, string $bucketId, string $fileId): array { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); + if (!$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 6cbaeaa915..3d1f6eef38 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -66,23 +65,23 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents): void { /** * @var Document $bucket * @var Document $file */ - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $validator = new Authorization(Database::PERMISSION_UPDATE); + $bucketPermission = $validator->isValid($bucket->getUpdate()); if ($fileSecurity) { - $filePermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); + $filePermission = $validator->isValid($file->getUpdate()); if (!$bucketPermission && !$filePermission) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 13da92cbc6..8a9301713b 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -13,7 +13,6 @@ use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; @@ -58,13 +57,12 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index cc6981fa1b..3e35c1c1fa 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -31,7 +31,6 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') - ->inject('authorisation') ->callback($this->action(...)); } @@ -48,8 +47,8 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, - Authorization $authorization ): void { + Authorization::disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); @@ -67,14 +66,14 @@ class Migrate extends Action $count = 0; $total = $dbForPlatform->count('projects') + 1; - $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total, $authorization) { + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); $dbForProject->disableValidation(); try { $migration - ->setProject($project, $dbForProject, $dbForPlatform, $authorization, $getProjectDB) + ->setProject($project, $dbForProject, $dbForPlatform, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -89,7 +88,7 @@ class Migrate extends Action try { $migration - ->setProject($console, $getProjectDB($console), $dbForPlatform, $authorization, $getProjectDB) + ->setProject($console, $getProjectDB($console), $dbForPlatform, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 19ed3bc099..9698fe9034 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -8,6 +8,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; @@ -60,7 +61,7 @@ abstract class ScheduleBase extends Action $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $dbForPlatform->updateDocument('projects', $project->getId(), $project); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index 6d04d2109a..b64dd61f86 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -8,6 +8,7 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\System\System; /** @@ -60,7 +61,9 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue, $dbForPlatform) { + Console::loop(function () use ($queue) { + Authorization::disable(); + Authorization::setDefaultStatus(false); $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); /** diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 33ebd39092..5132687279 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -21,7 +21,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; -use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -59,7 +58,6 @@ class Certificates extends Action ->inject('log') ->inject('certificates') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -74,8 +72,6 @@ class Certificates extends Action * @param Certificate $queueForCertificates * @param Log $log * @param CertificatesAdapter $certificates - * @param array $plan - * @param ValidatorAuthorization $authorization * @return void * @throws Throwable * @throws \Utopia\Database\Exception @@ -91,8 +87,7 @@ class Certificates extends Action Certificate $queueForCertificates, Log $log, CertificatesAdapter $certificates, - array $plan, - ValidatorAuthorization $authorization, + array $plan ): void { $payload = $message->getPayload() ?? []; @@ -111,11 +106,11 @@ class Certificates extends Action switch ($action) { case Certificate::ACTION_DOMAIN_VERIFICATION: - $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $authorization, $validationDomain); + $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $validationDomain); break; case Certificate::ACTION_GENERATION: - $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); + $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $validationDomain); break; default: @@ -132,12 +127,10 @@ class Certificates extends Action * @param Realtime $queueForRealtime * @param Certificate $queueForCertificates * @param Log $log - * @param ValidatorAuthorization $authorization * @param string|null $validationDomain * @return void + * @throws Throwable * @throws \Utopia\Database\Exception - * @throws NotFound - * @throws \Utopia\Database\Exception\Query */ private function handleDomainVerificationAction( Domain $domain, @@ -148,13 +141,12 @@ class Certificates extends Action Realtime $queueForRealtime, Certificate $queueForCertificates, Log $log, - ValidatorAuthorization $authorization, ?string $validationDomain = null ): void { // Get rule $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ + ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); @@ -203,23 +195,15 @@ class Certificates extends Action * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents - * @param Webhook $queueForWebhooks * @param Func $queueForFunctions * @param Realtime $queueForRealtime - * @param Log $log * @param CertificatesAdapter $certificates - * @param ValidatorAuthorization $authorization * @param bool $skipRenewCheck * @param array $plan * @param string|null $validationDomain * @return void - * @throws Authorization - * @throws Conflict - * @throws NotFound - * @throws Structure * @throws Throwable * @throws \Utopia\Database\Exception - * @throws \Utopia\Database\Exception\Query */ private function handleCertificateGenerationAction( Domain $domain, @@ -232,7 +216,6 @@ class Certificates extends Action Realtime $queueForRealtime, Log $log, CertificatesAdapter $certificates, - ValidatorAuthorization $authorization, bool $skipRenewCheck = false, array $plan = [], ?string $validationDomain = null @@ -269,8 +252,8 @@ class Certificates extends Action // Get rule document for domain // TODO: (@Meldiron) Remove after 1.7.x migration $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ + ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 9687f4f4bb..0b2f7c75ae 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -19,10 +19,12 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; +use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -201,6 +203,7 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void + * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -999,14 +1002,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); + $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); if ($bucket->isEmpty()) { Console::error('Failed to get bucket for deployment screenshots'); return; } foreach ($screenshotIds as $id) { - $file = $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id); + $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index a54b982634..fba5154079 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -15,6 +15,7 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; @@ -336,6 +337,7 @@ class Functions extends Action * @param string|null $eventData * @param string|null $executionId * @return void + * @throws Authorization * @throws Structure * @throws \Utopia\Database\Exception * @throws Conflict diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 6ef2f1899c..e1039510f4 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -80,7 +80,6 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -98,7 +97,6 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, - Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -136,13 +134,7 @@ class Migrations extends Action } try { - $this->processMigration( - $migration, - $queueForRealtime, - $queueForMails, - $platform, - $authorization - ); + $this->processMigration($migration, $queueForRealtime, $queueForMails, $platform); } finally { $this->dbForProject = null; $this->dbForPlatform = null; @@ -153,7 +145,7 @@ class Migrations extends Action $this->plan = []; $this->sourceReport = []; - \gc_collect_cycles(); + gc_collect_cycles(); } } @@ -327,7 +319,6 @@ class Migrations extends Action Realtime $queueForRealtime, Mail $queueForMails, array $platform, - Authorization $authorization, ): void { $project = $this->project; @@ -444,14 +435,14 @@ class Migrations extends Action $destination?->success(); $source?->success(); - // TODO: Move to CSV hook + // todo: Move to CSV hook if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform); } } } finally { - $source?->cleanup(); - $destination?->cleanup(); + $source?->cleanUp(); + $destination?->cleanUp(); $transfer = null; $source = null; @@ -466,10 +457,11 @@ class Migrations extends Action * @param Document $project * @param Document $migration * @param Mail $queueForMails - * @param Realtime $queueForRealtime - * @param array $platform - * @param Authorization $authorization * @return void + * @throws AuthorizationException + * @throws Structure + * @throws \Utopia\Database\Exception + * @throws Exception */ protected function handleCSVExportComplete( Document $project, @@ -477,7 +469,6 @@ class Migrations extends Action Mail $queueForMails, Realtime $queueForRealtime, array $platform, - Authorization $authorization, ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -491,7 +482,7 @@ class Migrations extends Action throw new \Exception('User ' . $userInternalId . ' not found'); } - $bucket = $authorization->skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new \Exception('Bucket not found'); } diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index cbd22aaee5..a85b0a897c 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -7,6 +7,7 @@ use Utopia\Auth\Proofs\Token; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; class User extends Document @@ -35,11 +36,11 @@ class User extends Document * * @return array */ - public function getRoles($authorization): array + public function getRoles(): array { $roles = []; - if (!$this->isPrivileged($authorization->getRoles()) && !$this->isApp($authorization->getRoles())) { + if (!$this->isPrivileged(Authorization::getRoles()) && !$this->isApp(Authorization::getRoles())) { if ($this->getId()) { $roles[] = Role::user($this->getId())->toString(); $roles[] = Role::users()->toString(); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index c87279f126..cb449e6ffa 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -214,7 +214,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = $this->authorization->getRoles(); + $roles = Authorization::getRoles(); $isAppUser = User::isApp($roles); if ($isAppUser) { @@ -237,11 +237,4 @@ class Request extends UtopiaRequest ksort($params); return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } - - private ?Authorization $authorization = null; - - public function setAuthorization(Authorization $authorization): void - { - $this->authorization = $authorization; - } } diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 6d47d4d150..56fed746d9 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -10,7 +10,7 @@ abstract class Filter private array $params; private ?Database $dbForProject; - public function __construct(?Database $dbForProject = null, array $params = []) + public function __construct(Database $dbForProject = null, array $params = []) { $this->params = $params; $this->dbForProject = $dbForProject; diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index e3d5fe2f79..69e7da6b7a 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -7,6 +7,7 @@ use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; class V20 extends Filter { @@ -137,7 +138,7 @@ class V20 extends Filter } try { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $database = Authorization::skip(fn () => $dbForProject->getDocument( 'databases', $databaseId )); @@ -149,7 +150,7 @@ class V20 extends Filter } try { - $collection = $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $collection = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId )); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index f2ac486f82..1dfaa1a41f 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -483,7 +483,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = $this->authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = DBUser::isPrivileged($roles); $isAppUser = DBUser::isApp($roles); @@ -651,11 +651,4 @@ class Response extends SwooleResponse self::$showSensitive = false; } } - - private ?Authorization $authorization = null; - - public function setAuthorization(Authorization $authorization): void - { - $this->authorization = $authorization; - } } diff --git a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index 0c9854160e..6496aa285a 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,19 +17,6 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - - return $this->authorization; - } - public function createCollection(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ @@ -124,8 +111,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -147,7 +134,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } @@ -158,8 +145,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -235,7 +222,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index 84cb4bce3a..2f69c037d0 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -17,19 +17,6 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - return $this->authorization; - } - - public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ @@ -124,8 +111,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicRows = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -147,7 +134,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } @@ -158,8 +145,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -235,7 +222,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateRow['headers']['status-code']); foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } diff --git a/tests/e2e/Services/Tokens/TokensBase.php b/tests/e2e/Services/Tokens/TokensBase.php index ca6feed5fa..a4461c06c2 100644 --- a/tests/e2e/Services/Tokens/TokensBase.php +++ b/tests/e2e/Services/Tokens/TokensBase.php @@ -94,7 +94,7 @@ trait TokensBase $this->assertEquals(401, $failedPreview['body']['code']); $this->assertEquals(401, $failedPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedPreview['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedPreview['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedPreview['body']['message']); // Extended file preview. Should fail as an anonymous user with no form of any access to the file. $failedCustomPreview = $this->client->call( @@ -113,7 +113,7 @@ trait TokensBase $this->assertEquals(401, $failedCustomPreview['body']['code']); $this->assertEquals(401, $failedCustomPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedCustomPreview['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedCustomPreview['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedCustomPreview['body']['message']); // File view. Should fail as an anonymous user with no form of any access to the file. $failedView = $this->client->call( @@ -124,7 +124,7 @@ trait TokensBase $this->assertEquals(401, $failedView['body']['code']); $this->assertEquals(401, $failedView['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedView['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedView['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedView['body']['message']); // File download. Should fail as an anonymous user with no form of any access to the file. $failedDownload = $this->client->call( @@ -135,7 +135,7 @@ trait TokensBase $this->assertEquals(401, $failedDownload['body']['code']); $this->assertEquals(401, $failedDownload['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedDownload['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedDownload['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedDownload['body']['message']); return $data; } diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 7df5b8d1e6..42e433568f 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -7,7 +7,6 @@ use Appwrite\Utopia\Database\Documents\User; use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -34,19 +33,6 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; - - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - return $this->authorization; - } - public function setUp(): void { /** @@ -79,7 +65,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -103,7 +89,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); diff --git a/tests/unit/Utopia/Database/Documents/UserTest.php b/tests/unit/Utopia/Database/Documents/UserTest.php index d5706e7bec..4675e8d73f 100644 --- a/tests/unit/Utopia/Database/Documents/UserTest.php +++ b/tests/unit/Utopia/Database/Documents/UserTest.php @@ -14,25 +14,13 @@ use Utopia\Database\Validator\Roles; class UserTest extends TestCase { - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - return $this->authorization; - } - /** * Reset Roles */ public function tearDown(): void { - $this->getAuthorization()->cleanRoles(); - $this->getAuthorization()->addRole(Role::any()->toString()); + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); } public function testSessionVerify(): void @@ -209,7 +197,7 @@ class UserTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -245,7 +233,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -266,21 +254,21 @@ class UserTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles); // Enable single verification type $user['emailVerification'] = true; - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); } public function testPrivilegedUserRoles(): void { - $this->getAuthorization()->addRole(User::ROLE_OWNER); + Authorization::setRole(User::ROLE_OWNER); $user = new User([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -305,7 +293,8 @@ class UserTest extends TestCase ] ] ]); - $roles = $user->getRoles($this->getAuthorization()); + + $roles = $user->getRoles(); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -323,7 +312,7 @@ class UserTest extends TestCase public function testAppUserRoles(): void { - $this->getAuthorization()->addRole(User::ROLE_APPS); + Authorization::setRole(User::ROLE_APPS); $user = new User([ '$id' => ID::custom('123'), 'memberships' => [ @@ -347,7 +336,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); From e887859cc0e849e3567911d124e9947d8172cb85 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 14 Jan 2026 00:57:40 +0000 Subject: [PATCH 21/52] feat: implement afterDeploymentSuccess hook in builds worker and invoke it post-deployment --- .../Modules/Functions/Workers/Builds.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 285f78319a..68027620e4 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1024,6 +1024,11 @@ class Builds extends Action Console::log('Deployment activated'); } + $this->afterDeploymentSuccess( + $project, + $deployment, + ); + // Send realtime event after updating the associated resource so that Console will have the resource's deployment details when re-fetching. $queueForRealtime ->setPayload($deployment->getArrayCopy()) @@ -1256,6 +1261,19 @@ class Builds extends Action } } + protected function afterDeploymentSuccess( + Document $project, + Document $deployment, + ): void { + if (!($project instanceof Document)) { + throw new Exception('project must be an instance of Document'); + } + + if (!($deployment instanceof Document)) { + throw new Exception('deployment must be an instance of Document'); + } + } + protected function getRuntime(Document $resource, string $version): array { $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); From 5469b783677cb50fd6c010032eaeb182ae41ab48 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 14 Jan 2026 00:59:22 +0000 Subject: [PATCH 22/52] feat: add afterDeploymentSuccess hook to handle post-deployment actions --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 68027620e4..414696306f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1261,6 +1261,13 @@ class Builds extends Action } } + /** + * Hook to run after deployment is activated + * + * @param Document $project + * @param Document $deployment + * @return void + */ protected function afterDeploymentSuccess( Document $project, Document $deployment, From 5c915ef92f876669daad308417faf7fa9fb0325b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 Jan 2026 19:07:49 +1300 Subject: [PATCH 23/52] Reapply "Merge pull request #11099 from appwrite/feat-auth-instance" This reverts commit 321fc8ee705c6f1022d84dc12fb267b85505b38d. --- app/cli.php | 28 ++- app/config/storage/resource_limits.php | 4 +- app/controllers/api/account.php | 146 ++++++++------ app/controllers/api/graphql.php | 5 +- app/controllers/api/health.php | 18 +- app/controllers/api/messaging.php | 65 +++--- app/controllers/api/migrations.php | 14 +- app/controllers/api/project.php | 9 +- app/controllers/api/teams.php | 63 +++--- app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 60 +++--- app/controllers/general.php | 187 +++++++++--------- app/controllers/shared/api.php | 53 ++--- app/controllers/shared/api/auth.php | 7 +- app/http.php | 28 +-- app/init/database/filters.php | 47 +++-- app/init/resources.php | 106 +++++----- app/realtime.php | 41 ++-- app/worker.php | 53 +++-- composer.json | 10 +- composer.lock | 107 +++++----- src/Appwrite/Databases/TransactionState.php | 10 +- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Avatars/Http/Action.php | 10 +- .../Modules/Avatars/Http/Browsers/Get.php | 2 +- .../Avatars/Http/Cards/Cloud/Back/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/Front/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/OG/Get.php | 7 +- .../Modules/Avatars/Http/CreditCards/Get.php | 2 +- .../Modules/Avatars/Http/Flags/Get.php | 2 +- .../Platform/Modules/Compute/Base.php | 41 +++- .../Modules/Console/Http/Resources/Get.php | 6 +- .../Collections/Attributes/Action.php | 10 +- .../Collections/Attributes/Boolean/Create.php | 6 +- .../Collections/Attributes/Boolean/Update.php | 5 +- .../Attributes/Datetime/Create.php | 7 +- .../Attributes/Datetime/Update.php | 5 +- .../Collections/Attributes/Delete.php | 5 +- .../Collections/Attributes/Email/Create.php | 7 +- .../Collections/Attributes/Email/Update.php | 5 +- .../Collections/Attributes/Enum/Create.php | 7 +- .../Collections/Attributes/Enum/Update.php | 5 +- .../Collections/Attributes/Float/Create.php | 6 +- .../Collections/Attributes/Float/Update.php | 5 +- .../Databases/Collections/Attributes/Get.php | 5 +- .../Collections/Attributes/IP/Create.php | 7 +- .../Collections/Attributes/IP/Update.php | 5 +- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Integer/Update.php | 5 +- .../Collections/Attributes/Line/Create.php | 6 +- .../Collections/Attributes/Line/Update.php | 5 +- .../Collections/Attributes/Point/Create.php | 6 +- .../Collections/Attributes/Point/Update.php | 5 +- .../Collections/Attributes/Polygon/Create.php | 6 +- .../Collections/Attributes/Polygon/Update.php | 5 +- .../Attributes/Relationship/Create.php | 7 +- .../Attributes/Relationship/Update.php | 6 +- .../Collections/Attributes/String/Create.php | 8 +- .../Collections/Attributes/String/Update.php | 6 +- .../Collections/Attributes/URL/Create.php | 7 +- .../Collections/Attributes/URL/Update.php | 6 +- .../Collections/Attributes/XList.php | 5 +- .../Http/Databases/Collections/Create.php | 5 +- .../Http/Databases/Collections/Delete.php | 5 +- .../Collections/Documents/Action.php | 7 +- .../Documents/Attribute/Decrement.php | 13 +- .../Documents/Attribute/Increment.php | 13 +- .../Collections/Documents/Create.php | 43 ++-- .../Collections/Documents/Delete.php | 17 +- .../Databases/Collections/Documents/Get.php | 12 +- .../Collections/Documents/Logs/XList.php | 5 +- .../Collections/Documents/Update.php | 26 +-- .../Collections/Documents/Upsert.php | 26 +-- .../Databases/Collections/Documents/XList.php | 16 +- .../Http/Databases/Collections/Get.php | 5 +- .../Databases/Collections/Indexes/Create.php | 5 +- .../Databases/Collections/Indexes/Delete.php | 5 +- .../Databases/Collections/Indexes/Get.php | 5 +- .../Databases/Collections/Indexes/XList.php | 7 +- .../Http/Databases/Collections/Logs/XList.php | 39 ++-- .../Http/Databases/Collections/Update.php | 5 +- .../Http/Databases/Collections/Usage/Get.php | 5 +- .../Http/Databases/Collections/XList.php | 5 +- .../Http/Databases/Transactions/Create.php | 5 +- .../Transactions/Operations/Create.php | 34 ++-- .../Http/Databases/Transactions/Update.php | 37 ++-- .../Databases/Http/Databases/Usage/Get.php | 5 +- .../Databases/Http/Databases/Usage/XList.php | 5 +- .../Tables/Columns/Boolean/Create.php | 1 + .../Tables/Columns/Boolean/Update.php | 1 + .../Tables/Columns/Datetime/Create.php | 1 + .../Tables/Columns/Datetime/Update.php | 1 + .../Http/TablesDB/Tables/Columns/Delete.php | 1 + .../TablesDB/Tables/Columns/Email/Create.php | 1 + .../TablesDB/Tables/Columns/Email/Update.php | 1 + .../TablesDB/Tables/Columns/Enum/Create.php | 1 + .../TablesDB/Tables/Columns/Enum/Update.php | 1 + .../TablesDB/Tables/Columns/Float/Create.php | 1 + .../TablesDB/Tables/Columns/Float/Update.php | 1 + .../Http/TablesDB/Tables/Columns/Get.php | 1 + .../TablesDB/Tables/Columns/IP/Create.php | 1 + .../TablesDB/Tables/Columns/IP/Update.php | 1 + .../Tables/Columns/Integer/Create.php | 1 + .../Tables/Columns/Integer/Update.php | 1 + .../TablesDB/Tables/Columns/Line/Create.php | 1 + .../TablesDB/Tables/Columns/Line/Update.php | 1 + .../TablesDB/Tables/Columns/Point/Create.php | 1 + .../TablesDB/Tables/Columns/Point/Update.php | 1 + .../Tables/Columns/Polygon/Create.php | 1 + .../Tables/Columns/Polygon/Update.php | 1 + .../Tables/Columns/Relationship/Create.php | 1 + .../Tables/Columns/Relationship/Update.php | 1 + .../TablesDB/Tables/Columns/String/Create.php | 1 + .../TablesDB/Tables/Columns/String/Update.php | 1 + .../TablesDB/Tables/Columns/URL/Create.php | 1 + .../TablesDB/Tables/Columns/URL/Update.php | 1 + .../Http/TablesDB/Tables/Columns/XList.php | 1 + .../Databases/Http/TablesDB/Tables/Create.php | 1 + .../Databases/Http/TablesDB/Tables/Delete.php | 1 + .../Databases/Http/TablesDB/Tables/Get.php | 1 + .../Http/TablesDB/Tables/Indexes/Create.php | 2 + .../Http/TablesDB/Tables/Indexes/Delete.php | 1 + .../Http/TablesDB/Tables/Indexes/Get.php | 1 + .../Http/TablesDB/Tables/Indexes/XList.php | 1 + .../Http/TablesDB/Tables/Logs/XList.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Delete.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Update.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Upsert.php | 1 + .../TablesDB/Tables/Rows/Column/Decrement.php | 1 + .../TablesDB/Tables/Rows/Column/Increment.php | 1 + .../Http/TablesDB/Tables/Rows/Create.php | 1 + .../Http/TablesDB/Tables/Rows/Delete.php | 1 + .../Http/TablesDB/Tables/Rows/Get.php | 1 + .../Http/TablesDB/Tables/Rows/Logs/XList.php | 1 + .../Http/TablesDB/Tables/Rows/Update.php | 1 + .../Http/TablesDB/Tables/Rows/Upsert.php | 1 + .../Http/TablesDB/Tables/Rows/XList.php | 1 + .../Databases/Http/TablesDB/Tables/Update.php | 1 + .../Http/TablesDB/Tables/Usage/Get.php | 1 + .../Databases/Http/TablesDB/Tables/XList.php | 1 + .../Http/TablesDB/Transactions/Create.php | 1 + .../Transactions/Operations/Create.php | 1 + .../Http/TablesDB/Transactions/Update.php | 1 + .../Databases/Http/TablesDB/Usage/Get.php | 1 + .../Databases/Http/TablesDB/Usage/XList.php | 1 + .../Functions/Http/Deployments/Create.php | 5 +- .../Http/Deployments/Template/Create.php | 12 +- .../Functions/Http/Deployments/Vcs/Create.php | 2 +- .../Functions/Http/Executions/Create.php | 25 +-- .../Functions/Http/Executions/Delete.php | 6 +- .../Modules/Functions/Http/Executions/Get.php | 10 +- .../Functions/Http/Executions/XList.php | 10 +- .../Functions/Http/Functions/Create.php | 9 +- .../Functions/Http/Functions/Delete.php | 6 +- .../Http/Functions/Deployment/Update.php | 10 +- .../Functions/Http/Functions/Update.php | 6 +- .../Modules/Functions/Http/Usage/Get.php | 5 +- .../Modules/Functions/Http/Usage/XList.php | 5 +- .../Functions/Http/Variables/Create.php | 6 +- .../Functions/Http/Variables/Delete.php | 6 +- .../Functions/Http/Variables/Update.php | 6 +- .../Modules/Functions/Workers/Builds.php | 8 +- .../Modules/Sites/Http/Deployments/Create.php | 10 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Template/Create.php | 9 +- .../Sites/Http/Deployments/Vcs/Create.php | 6 +- .../Sites/Http/Sites/Deployment/Update.php | 8 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 6 +- .../Modules/Sites/Http/Usage/XList.php | 5 +- .../Storage/Http/Buckets/Files/Create.php | 36 ++-- .../Storage/Http/Buckets/Files/Delete.php | 22 ++- .../Http/Buckets/Files/Download/Get.php | 18 +- .../Storage/Http/Buckets/Files/Get.php | 16 +- .../Http/Buckets/Files/Preview/Get.php | 22 ++- .../Storage/Http/Buckets/Files/Push/Get.php | 12 +- .../Storage/Http/Buckets/Files/Update.php | 24 +-- .../Storage/Http/Buckets/Files/View/Get.php | 18 +- .../Storage/Http/Buckets/Files/XList.php | 22 ++- .../Modules/Storage/Http/Buckets/Get.php | 23 ++- .../Modules/Storage/Http/Buckets/XList.php | 35 ++-- .../Modules/Storage/Http/Usage/Get.php | 5 +- .../Modules/Storage/Http/Usage/XList.php | 5 +- .../Http/Tokens/Buckets/Files/Action.php | 17 +- .../Http/Tokens/Buckets/Files/Create.php | 11 +- .../Http/Tokens/Buckets/Files/XList.php | 6 +- src/Appwrite/Platform/Tasks/Migrate.php | 9 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 3 +- .../Platform/Tasks/StatsResources.php | 5 +- .../Platform/Workers/Certificates.php | 33 +++- src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Platform/Workers/Functions.php | 2 - src/Appwrite/Platform/Workers/Migrations.php | 31 +-- .../Utopia/Database/Documents/User.php | 5 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 5 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 25 ++- .../DatabasesPermissionsGuestTest.php | 25 ++- tests/e2e/Services/Tokens/TokensBase.php | 8 +- .../unit/Messaging/MessagingChannelsTest.php | 18 +- .../Utopia/Database/Documents/UserTest.php | 33 ++-- 202 files changed, 1479 insertions(+), 978 deletions(-) diff --git a/app/cli.php b/app/cli.php index 07966b2450..7493d10ab3 100644 --- a/app/cli.php +++ b/app/cli.php @@ -41,8 +41,6 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false)); // require controllers after overwriting runtimes require_once __DIR__ . '/controllers/general.php'; -Authorization::disable(); - CLI::setResource('register', fn () => $register); CLI::setResource('cache', function ($pools) { @@ -60,7 +58,13 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('dbForPlatform', function ($pools, $cache) { +CLI::setResource('authorization', function () { + $authorization = new Authorization(); + $authorization->disable(); + return $authorization; +}, []); + +CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -74,6 +78,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -99,7 +104,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { } return $dbForPlatform; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('console', function () { return new Document(Config::getParam('console')); @@ -110,10 +115,10 @@ CLI::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -146,6 +151,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); + $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -162,17 +168,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { +CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -182,6 +189,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) @@ -194,7 +202,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); diff --git a/app/config/storage/resource_limits.php b/app/config/storage/resource_limits.php index cfbcea5a47..43ed2b8b05 100644 --- a/app/config/storage/resource_limits.php +++ b/app/config/storage/resource_limits.php @@ -3,4 +3,6 @@ use Utopia\Image\Image; use Utopia\System\System; -Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); +if (\class_exists('Imagick')) { + Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); +} diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 2c481b500c..bcea3387a2 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -207,10 +207,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr } -$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $userFromRequest */ - $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -266,7 +266,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -275,7 +275,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + $authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -376,8 +376,9 @@ App::post('/v1/account') ->inject('user') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('hooks') - ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Hooks $hooks) { + ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Hooks $hooks) { $email = \strtolower($email); if ('console' === $project->getId()) { @@ -469,9 +470,9 @@ App::post('/v1/account') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -497,9 +498,9 @@ App::post('/v1/account') throw new Exception(Exception::USER_ALREADY_EXISTS); } - Authorization::unsetRole(Role::guests()->toString()); - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $authorization->removeRole(Role::guests()->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::users()->toString()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -976,7 +977,8 @@ App::post('/v1/account/sessions/email') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -1021,7 +1023,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) { @@ -1120,7 +1122,8 @@ App::post('/v1/account/sessions/anonymous') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1165,7 +1168,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; @@ -1191,7 +1194,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -1274,6 +1277,7 @@ App::post('/v1/account/sessions/token') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') +->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1470,7 +1474,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) { + ->inject('authorization') + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1726,7 +1731,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ]); $user->removeAttribute('$sequence'); - $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $userDoc = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), @@ -1744,8 +1749,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::users()->toString()); if (false === $user->getAttribute('status')) { // Account is blocked $failureRedirect(Exception::USER_BLOCKED); // User is in status blocked @@ -1816,7 +1821,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1840,7 +1845,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2077,7 +2082,8 @@ App::post('/v1/account/tokens/magic-url') ->inject('queueForMails') ->inject('proofForPassword') ->inject('platform') - ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform) { + ->inject('authorization') + ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2150,7 +2156,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); } $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); @@ -2170,7 +2176,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2356,7 +2362,8 @@ App::post('/v1/account/tokens/email') ->inject('queueForMails') ->inject('proofForPassword') ->inject('proofForCode') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2425,9 +2432,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2465,7 +2472,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2662,10 +2669,11 @@ App::put('/v1/account/sessions/magic-url') ->inject('queueForMails') ->inject('store') ->inject('proofForCode') - ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) { + ->inject('authorization') + ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode, $authorization) use ($createSession) { $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); $proofForToken->setHash(new Sha()); - $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode); + $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode, $authorization); }); App::put('/v1/account/sessions/phone') @@ -2711,6 +2719,7 @@ App::put('/v1/account/sessions/phone') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') + ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2754,7 +2763,8 @@ App::post('/v1/account/tokens/phone') ->inject('plan') ->inject('store') ->inject('proofForCode') - ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2804,9 +2814,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2852,7 +2862,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3243,7 +3253,8 @@ App::patch('/v1/account/email') ->inject('project') ->inject('hooks') ->inject('proofForPassword') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->inject('authorization') + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3295,7 +3306,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3311,7 +3322,7 @@ App::patch('/v1/account/email') $oldTarget = $user->find('identifier', $oldEmail, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); + $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate) { @@ -3352,8 +3363,9 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') - ->action(function (string $phone, string $password, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->inject('proofForPassword') +->inject('authorization') + ->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3368,7 +3380,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3399,7 +3411,7 @@ App::patch('/v1/account/phone') $oldTarget = $user->find('identifier', $oldPhone, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); + $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate $th) { @@ -3535,7 +3547,9 @@ App::post('/v1/account/recovery') ->inject('queueForMails') ->inject('queueForEvents') ->inject('proofForToken') - ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { + if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -3571,7 +3585,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3727,7 +3741,8 @@ App::put('/v1/account/recovery') ->inject('hooks') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { +->inject('authorization') + ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ $profile = $dbForProject->getDocument('users', $userId); @@ -3741,7 +3756,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $newPassword = $proofForPassword->hash($password); @@ -3844,7 +3859,8 @@ App::post('/v1/account/verifications/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('proofForToken') - ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3873,7 +3889,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4072,9 +4088,10 @@ App::put('/v1/account/verifications/email') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForToken') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4086,7 +4103,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -4146,7 +4163,8 @@ App::post('/v1/account/verifications/phone') ->inject('queueForStatsUsage') ->inject('plan') ->inject('proofForCode') - ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -4185,7 +4203,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4291,9 +4309,10 @@ App::put('/v1/account/verifications/phone') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForCode') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4305,7 +4324,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -4358,12 +4377,13 @@ App::post('/v1/account/targets/push') ->inject('dbForProject') ->inject('store') ->inject('proofForToken') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken, Authorization $authorization) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); @@ -4438,9 +4458,10 @@ App::put('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); @@ -4503,8 +4524,9 @@ App::delete('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + ->inject('authorization') + ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index baf0ba1512..e0cc4181db 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -28,11 +28,12 @@ use Utopia\Validator\Text; App::init() ->groups(['graphql']) ->inject('project') - ->action(function (Document $project) { + ->inject('authorization') + ->action(function (Document $project, Authorization $authorization) { if ( array_key_exists('graphql', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['graphql'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 907ed54de8..d6388185d3 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -27,6 +27,7 @@ use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Config\Config; use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -101,7 +102,8 @@ App::get('/v1/health/db') )) ->inject('response') ->inject('pools') - ->action(function (Response $response, Group $pools) { + ->inject('authorization') + ->action(action: function (Response $response, Group $pools, Authorization $authorization) { $output = []; $failures = []; @@ -114,14 +116,14 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); - + $adapter->setAuthorization($authorization); $checkStart = \microtime(true); if ($adapter->ping()) { $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $database; @@ -132,6 +134,8 @@ App::get('/v1/health/db') } } + // Only throw error if ALL databases failed (no successful pings) + // This allows partial failures in environments where not all DBs are ready if (!empty($failures)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); } @@ -181,7 +185,7 @@ App::get('/v1/health/cache') $output[] = new Document([ 'name' => $key . " ($cache)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $cache; @@ -241,7 +245,7 @@ App::get('/v1/health/pubsub') $output[] = new Document([ 'name' => $key . " ($pubsub)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $pubsub; @@ -823,7 +827,7 @@ App::get('/v1/health/storage/local') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -875,7 +879,7 @@ App::get('/v1/health/storage') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 0b6a314dc5..6ac36fe3c0 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -36,6 +36,7 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -1073,8 +1074,9 @@ App::get('/v1/messaging/providers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1100,7 +1102,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); @@ -2481,8 +2483,9 @@ App::get('/v1/messaging/topics') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2508,7 +2511,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Topic '{$topicId}' for the 'cursor' value not found."); @@ -2782,29 +2785,27 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) { + ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { $subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId; - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); } - - $validator = new Authorization('subscribe'); - - if (!$validator->isValid($topic->getAttribute('subscribe'))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2837,7 +2838,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2882,8 +2883,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2894,7 +2896,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2917,7 +2919,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Subscriber '{$subscriberId}' for the 'cursor' value not found."); @@ -2931,10 +2933,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) { - return function () use ($subscriber, $dbForProject) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $authorization) { + return function () use ($subscriber, $dbForProject, $authorization) { + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); return $subscriber ->setAttribute('target', $target) @@ -3067,9 +3069,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Authorization $authorization, Response $response) { + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3081,8 +3084,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') throw new Exception(Exception::SUBSCRIBER_NOT_FOUND); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber ->setAttribute('target', $target) @@ -3118,9 +3121,10 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3143,7 +3147,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3702,8 +3706,9 @@ App::get('/v1/messaging/messages') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3729,7 +3734,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('messages', $messageId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found."); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 3989ad3298..1a17853577 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -342,6 +342,7 @@ App::post('/v1/migrations/csv/imports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('platform') ->inject('deviceForFiles') @@ -356,6 +357,7 @@ App::post('/v1/migrations/csv/imports') Response $response, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, Document $project, array $platform, Device $deviceForFiles, @@ -363,7 +365,7 @@ App::post('/v1/migrations/csv/imports') Event $queueForEvents, Migration $queueForMigrations ) { - $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -374,7 +376,7 @@ App::post('/v1/migrations/csv/imports') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -491,6 +493,7 @@ App::post('/v1/migrations/csv/exports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('platform') ->inject('queueForEvents') @@ -509,6 +512,7 @@ App::post('/v1/migrations/csv/exports') Response $response, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, Document $project, array $platform, Event $queueForEvents, @@ -520,7 +524,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); + $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -533,12 +537,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $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 = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index a57675d3e8..cda03f923a 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -45,9 +45,10 @@ App::get('/v1/project/usage') ->inject('response') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('getLogsDB') ->inject('smsRates') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) { + ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, Authorization $authorization, callable $getLogsDB, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -102,7 +103,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { + $authorization->skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; @@ -286,7 +287,7 @@ App::get('/v1/project/usage') }, $dbForProject->find('functions')); // This total is includes free and paid SMS usage - $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ + $authPhoneTotal = $authorization->skip(fn () => $dbForProject->sum('stats', 'value', [ Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), @@ -294,7 +295,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ + $authPhoneMetrics = $authorization->skip(fn () => $dbForProject->find('stats', [ Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 1f8555b6cd..aa67a90885 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -86,16 +86,17 @@ App::post('/v1/teams') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($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)), @@ -491,6 +492,7 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -500,9 +502,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('plan') ->inject('proofForPassword') ->inject('proofForToken') - ->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 $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { - $isAppUser = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { + $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -619,13 +621,13 @@ App::post('/v1/teams/:teamId/memberships') ]); try { - $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument)); + $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', $userDocument)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); 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'); @@ -661,11 +663,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { $membership->setAttribute('secret', $proofForToken->hash($secret)); @@ -677,7 +679,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + $authorization->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } else { throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); @@ -863,7 +865,8 @@ App::get('/v1/teams/:teamId/memberships') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -933,7 +936,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1004,7 +1007,8 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); @@ -1024,7 +1028,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1103,8 +1107,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->inject('user') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1121,9 +1126,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($authorization->getRoles()); + $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { // Quick check: fetch up to 2 owners to determine if only one exists @@ -1204,12 +1209,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') ->inject('store') ->inject('proofForToken') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1218,7 +1224,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::MEMBERSHIP_NOT_FOUND); } - $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); @@ -1254,11 +1260,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->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))); // Create session for the user if not logged in if (!$hasSession) { - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1286,7 +1292,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - Authorization::setRole(Role::user($userId)->toString()); + $authorization->addRole(Role::user($userId)->toString()); $encoded = $store ->setProperty('id', $user->getId()) @@ -1324,7 +1330,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1368,8 +1374,9 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('project') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1427,7 +1434,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); } $queueForEvents diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bbe1d8a84a..a963284538 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2678,8 +2678,8 @@ App::get('/v1/users/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('register') - ->action(function (string $range, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -2689,7 +2689,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 4249dbfd48..2270f4fd89 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -76,7 +76,7 @@ use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, array $platform) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Authorization $authorization, Build $queueForBuilds, callable $getProjectDB, Request $request, array $platform) { $errors = []; foreach ($repositories as $repository) { try { @@ -87,12 +87,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); - $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -141,7 +141,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -180,7 +180,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } else { @@ -191,7 +191,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ + $latestComment = $authorization->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -212,7 +212,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -251,7 +251,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -294,7 +294,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -334,7 +334,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); - Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); + $authorization->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); @@ -344,7 +344,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -377,7 +377,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -408,7 +408,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -460,7 +460,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if ($lockAcquired) { // Wrap in try/finally to ensure lock file gets deleted try { - $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : ''; @@ -472,7 +472,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()); } } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -1476,11 +1476,12 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1516,14 +1517,14 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find resourceId from relevant resources table - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push (not committed by us) and not when branch is created or deleted if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1536,16 +1537,16 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - Authorization::skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -1574,12 +1575,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1588,7 +1589,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1599,7 +1600,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1786,17 +1787,18 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = Authorization::skip(fn () => $dbForPlatform->findOne('repositories', [ + $repository = $authorization->skip(fn () => $dbForPlatform->findOne('repositories', [ Query::equal('$id', [$repositoryId]), Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1814,7 +1816,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1846,7 +1848,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerCommitMessage = $pullRequestResponse['title'] ?? ''; $providerCommitUrl = $pullRequestResponse['html_url'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index ec8cfef775..671c948e93 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -59,7 +59,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -67,16 +67,16 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = Authorization::skip(function () use ($dbForPlatform, $host, $isMd5) { - if ($isMd5) { - return $dbForPlatform->getDocument('rules', md5($host)); - } - - return $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$host]), - ]) ?? new Document(); - }); + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + } else { + $rule = $authorization->skip( + fn () => $dbForPlatform->find('rules', [ + Query::equal('domain', [$host]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } $errorView = __DIR__ . '/../views/general/error.phtml'; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -111,7 +111,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = Authorization::skip( + $project = $authorization->skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -119,7 +119,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -158,7 +158,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw /** @var Document $deployment */ if (!empty($rule->getAttribute('deploymentId', ''))) { - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); } else { // 1.6.x DB schema compatibility // TODO: Make sure deploymentId is never empty, and remove this code @@ -172,15 +172,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // Document of site or function $resource = $resourceType === 'function' ? - Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : - Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId)); + $authorization->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : + $authorization->skip(fn () => $dbForProject->getDocument('sites', $resourceId)); // ID of active deployments // Attempts to use attribute from both schemas (1.6 and 1.7) $activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', '')); // Get deployment document, as intended originally - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -199,8 +199,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $resource = $type === 'function' ? - Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : - Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); + $authorization->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + $authorization->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); @@ -242,7 +242,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $userExists = false; $userId = $payload['userId'] ?? ''; if (!empty($userId)) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -255,7 +255,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); if (!$project->isEmpty() && isset($user)) { $teamId = $project->getAttribute('teamId', ''); $membership = $user->find('teamId', $teamId, 'memberships'); @@ -862,15 +862,16 @@ App::init() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { /* * Appwrite Router */ $hostname = $request->getHostname() ?? ''; $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain - if (!in_array($hostname, $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1033,7 +1034,8 @@ App::init() ->inject('dbForPlatform') ->inject('queueForCertificates') ->inject('platform') - ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform) { + ->inject('authorization') + ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) { $hostname = $request->getHostname(); $cache = Config::getParam('hostnames', []); $platformHostnames = $platform['hostnames'] ?? []; @@ -1061,64 +1063,64 @@ App::init() } // 4. Check/create rule (requires DB access) - Authorization::disable(); - try { - // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $document = $isMd5 - ? $dbForPlatform->getDocument('rules', md5($domain->get())) - : $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$domain->get()]), + $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) { + try { + // TODO: (@Meldiron) Remove after 1.7.x migration + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $document = $isMd5 + ? $dbForPlatform->getDocument('rules', md5($domain->get())) + : $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]), + ]); + + if (!$document->isEmpty()) { + return; + } + + // 5. Create new rule + $owner = ''; + $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); + $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { + $funcDomain = $fallback; + } + + if ( + (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || + (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) + ) { + $owner = 'Appwrite'; + } + + $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); + $document = new Document([ + '$id' => $ruleId, + 'domain' => $domain->get(), + 'type' => 'api', + 'status' => 'verifying', + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getSequence(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') ]); - if (!$document->isEmpty()) { - return; + $dbForPlatform->createDocument('rules', $document); + + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + $queueForCertificates + ->setDomain($document) + ->setSkipRenewCheck(true) + ->trigger(); + } catch (Duplicate $e) { + Console::info('Certificate already exists'); + } finally { + $cache[$domain->get()] = true; + Config::setParam('hostnames', $cache); } - - // 5. Create new rule - $owner = ''; - $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); - $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - - if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { - $funcDomain = $fallback; - } - - if ( - (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || - (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) - ) { - $owner = 'Appwrite'; - } - - $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); - $document = new Document([ - '$id' => $ruleId, - 'domain' => $domain->get(), - 'type' => 'api', - 'status' => 'verifying', - 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), - 'search' => implode(' ', [$ruleId, $domain->get()]), - 'owner' => $owner, - 'region' => $console->getAttribute('region') - ]); - - $dbForPlatform->createDocument('rules', $document); - - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); - $queueForCertificates - ->setDomain($document) - ->setSkipRenewCheck(true) - ->trigger(); - } catch (Duplicate $e) { - Console::info('Certificate already exists'); - } finally { - $cache[$domain->get()] = true; - Config::setParam('hostnames', $cache); - Authorization::reset(); - } + }); }); App::options() @@ -1141,7 +1143,8 @@ App::options() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { /* * Appwrite Router */ @@ -1182,7 +1185,8 @@ App::error() ->inject('log') ->inject('queueForStatsUsage') ->inject('devKey') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { + ->inject('authorization') + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Document $devKey, Authorization $authorization) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1264,7 +1268,7 @@ App::error() * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { - if (!DBUser::isPrivileged(Authorization::getRoles())) { + if (!DBUser::isPrivileged($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1326,7 +1330,7 @@ App::error() $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', $authorization->getRoles()); try { /* add queries to log */ @@ -1530,13 +1534,14 @@ App::get('/robots.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1562,13 +1567,14 @@ App::get('/humans.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1652,7 +1658,8 @@ App::get('/v1/ping') ->inject('project') ->inject('dbForPlatform') ->inject('queueForEvents') - ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { + ->inject('authorization') + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1664,7 +1671,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - Authorization::skip(function () use ($dbForPlatform, $project) { + $authorization->skip(function () use ($dbForPlatform, $project) { $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 05c08a2231..23bbb12183 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -30,6 +30,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Queue\Publisher; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; @@ -233,7 +234,8 @@ App::init() ->inject('mode') ->inject('team') ->inject('apiKey') - ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) { $route = $utopia->getRoute(); /** @@ -318,7 +320,7 @@ App::init() // Handle special app role case if ($apiKey->getRole() === User::ROLE_APPS) { // Disable authorization checks for API keys - Authorization::setDefaultStatus(false); + $authorization->setDefaultStatus(false); $user = new User([ '$id' => '', @@ -392,14 +394,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - Authorization::setRole($role); - foreach ($user->getRoles() as $authRole) { - Authorization::setRole($authRole); + $authorization->addRole($role); + foreach ($user->getRoles($authorization) as $authRole) { + $authorization->addRole($authRole); } // Step 6: Update project and user last activity @@ -407,7 +409,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -442,7 +444,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -509,14 +511,15 @@ App::init() ->inject('devKey') ->inject('telemetry') ->inject('platform') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform) use ($usageDatabaseListener, $eventDatabaseListener) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -546,7 +549,7 @@ App::init() $closestLimit = null; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -657,10 +660,10 @@ App::init() if ($useCache) { $route = $utopia->match($request); $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; - $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged(Authorization::getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged($authorization->getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -677,10 +680,10 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -691,8 +694,7 @@ App::init() } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -703,7 +705,7 @@ App::init() if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -714,11 +716,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -814,8 +816,9 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') + ->inject('authorization') ->inject('timelimit') - ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, callable $timelimit) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -976,11 +979,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', 0); $now = DateTime::now(); if ($cacheLog->isEmpty()) { - Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ + $authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -990,7 +993,7 @@ App::shutdown() ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); - Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); + $authorization->skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); // Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load() $cache->save($key, $data['payload']); } @@ -1002,7 +1005,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index efa733fc34..c0f7494125 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -36,7 +36,8 @@ App::init() ->inject('request') ->inject('project') ->inject('geodb') - ->action(function (App $utopia, Request $request, Document $project, Reader $geodb) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) { $denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', ''); if (!empty($denylist && $project->getId() === 'console')) { $countries = explode(',', $denylist); @@ -49,8 +50,8 @@ App::init() $route = $utopia->match($request); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($authorization->getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index b7f857da48..5d08c53eee 100644 --- a/app/http.php +++ b/app/http.php @@ -27,7 +27,6 @@ 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\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Pools\Group; @@ -261,7 +260,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools); // create appwrite database, `dbForPlatform` is a direct access call. - createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) { + createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections, $app) { + $authorization = $app->getResource('authorization'); + if ($dbForPlatform->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) { $adapter = new AdapterDatabase($dbForPlatform); $audit = new Audit($adapter); @@ -321,9 +322,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } - if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + $authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('screenshots'), '$collection' => ID::custom('buckets'), 'name' => 'Screenshots', @@ -338,7 +339,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); Console::info(" └── Creating files collection for screenshots bucket..."); $files = $collections['buckets']['files'] ?? []; @@ -366,7 +367,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + $authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -458,8 +459,12 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool App::setResource('pools', fn () => $pools); try { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); + $authorization = $app->getResource('authorization'); + + $request->setAuthorization($authorization); + $response->setAuthorization($authorization); + $authorization->cleanRoles(); + $authorization->addRole(Role::any()->toString()); $app->run($request, $response); } catch (\Throwable $th) { @@ -501,7 +506,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); $log->addExtra('trace', $th->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []); $sdk = $route->getLabel("sdk", false); @@ -560,7 +565,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { /** @var Utopia\Database\Database $dbForPlatform */ $dbForPlatform = $app->getResource('dbForPlatform'); - Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { + Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) { try { $time = DateTime::now(); $limit = 1000; @@ -577,7 +582,8 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); + $authorization = $app->getResource('authorization'); + $results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries)); } catch (Throwable $th) { Console::error($th->getMessage()); } diff --git a/app/init/database/filters.php b/app/init/database/filters.php index c9ad3fce03..2b2e17b6a9 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -4,7 +4,6 @@ use Appwrite\OpenSSL\OpenSSL; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\System\System; Database::addFilter( @@ -70,11 +69,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $attributes = $database->find('attributes', [ + $attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), - ]); + ])); foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); @@ -105,12 +104,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('indexes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), - ]); + ])); } ); @@ -120,11 +119,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('platforms', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -134,12 +133,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('keys', [ Query::equal('resourceType', ['projects']), Query::equal('resourceInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -149,11 +148,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('devKeys', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -163,11 +162,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('webhooks', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -177,7 +176,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database->find('sessions', [ + return $database->getAuthorization()->skip(fn () => $database->find('sessions', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); @@ -190,7 +189,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -204,7 +203,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('challenges', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -218,7 +217,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('authenticators', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -232,7 +231,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -252,14 +251,14 @@ Database::addFilter( default => ['function', 'site'] }; - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('variables', [ Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', $resourceType), Query::orderAsc('resourceType'), Query::orderAsc(), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -295,11 +294,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('variables', [ Query::equal('resourceType', ['project']), Query::limit(APP_LIMIT_SUBQUERY) - ]); + ])); } ); @@ -332,7 +331,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) @@ -346,7 +345,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $targetIds = Authorization::skip(fn () => \array_map( + $targetIds = $database->getAuthorization()->skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ Query::equal('topicInternalId', [$document->getSequence()]), diff --git a/app/init/resources.php b/app/init/resources.php index a3aa3ae47c..371609da97 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -230,7 +230,7 @@ App::setResource('allowedSchemes', function (Document $project) { /** * Rule associated with a request origin. */ -App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project) { +App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) { $domain = \parse_url($request->getOrigin(), PHP_URL_HOST); if (empty($domain)) { return new Document(); @@ -238,7 +238,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do // TODO: (@Meldiron) Remove after 1.7.x migration $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = Authorization::skip(function () use ($dbForPlatform, $domain, $isMd5) { + $rule = $authorization->skip(function () use ($dbForPlatform, $domain, $isMd5) { if ($isMd5) { return $dbForPlatform->getDocument('rules', md5($domain)); } @@ -253,7 +253,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do } return $rule; -}, ['request', 'dbForPlatform', 'project']); +}, ['request', 'dbForPlatform', 'project', 'authorization']); /** * CORS service @@ -321,7 +321,7 @@ App::setResource('redirectValidator', function (Document $devKey, array $allowed return new Redirect($allowedHostnames, $allowedSchemes); }, ['devKey', 'allowedHostnames', 'allowedSchemes']); -App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) { +App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken, $authorization) { /** * Handles user authentication and session validation. * @@ -341,7 +341,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co * overwriting the previous value. */ - Authorization::setDefaultStatus(true); + $authorization->setDefaultStatus(true); $store->setKey('a_session_' . $project->getId()); @@ -408,7 +408,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co } // if (APP_MODE_ADMIN === $mode) { // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { - // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + // $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. // } else { // $user = new Document([]); // } @@ -440,9 +440,9 @@ App::setResource('user', function (string $mode, Document $project, Document $co $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']); -App::setResource('project', function ($dbForPlatform, $request, $console) { +App::setResource('project', function ($dbForPlatform, $request, $console, $authorization) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ @@ -453,10 +453,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $console; } - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForPlatform', 'request', 'console']); +}, ['dbForPlatform', 'request', 'console', 'authorization']); App::setResource('session', function (User $user, Store $store, Token $proofForToken) { if ($user->isEmpty()) { @@ -479,10 +479,6 @@ App::setResource('session', function (User $user, Store $store, Token $proofForT return; }, ['user', 'store', 'proofForToken']); -App::setResource('console', function () { - return new Document(Config::getParam('console')); -}, []); - App::setResource('store', function (): Store { return new Store(); }); @@ -513,7 +509,15 @@ App::setResource('proofForCode', function (): Code { return $code; }); -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + +App::setResource('authorization', function () { + return new Authorization(); +}, []); + +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -529,6 +533,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -550,13 +555,15 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); + +App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { -App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') @@ -566,12 +573,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $database->setDocumentType('users', User::class); return $database; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); -App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { $databases = []; - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -583,13 +590,15 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $configure = (function (Database $database) use ($project, $dsn) { + $configure = (function (Database $database) use ($project, $dsn, $authorization) { $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - $database->setDocumentType('users', User::class); + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES) + ->setDocumentType('users', User::class) + ; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -619,12 +628,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -App::setResource('getLogsDB', function (Group $pools, Cache $cache) { +App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, &$database) { + return function (?Document $project = null) use ($pools, $cache, $authorization, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int) $project->getSequence()); return $database; @@ -634,6 +643,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -646,7 +656,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); App::setResource('audit', function ($dbForProject) { $adapter = new AdapterDatabase($dbForProject); @@ -845,7 +855,7 @@ App::setResource('promiseAdapter', function ($register) { return $register->get('promiseAdapter'); }, ['register']); -App::setResource('schema', function ($utopia, $dbForProject) { +App::setResource('schema', function ($utopia, $dbForProject, $authorization) { $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); @@ -855,8 +865,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ + $attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) { + $attrs = $authorization->skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -930,7 +940,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { $urls, $params, ); -}, ['utopia', 'dbForProject']); +}, ['utopia', 'dbForProject', 'authorization']); App::setResource('gitHub', function (Cache $cache) { return new VcsGitHub($cache); @@ -958,7 +968,7 @@ App::setResource('smsRates', function () { return []; }); -App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) { +App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform, Authorization $authorization) { $devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', '')); // Check if given key match project's development keys @@ -977,7 +987,7 @@ App::setResource('devKey', function (Request $request, Document $project, array $accessedAt = $key->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DatabaseDateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -994,15 +1004,15 @@ App::setResource('devKey', function (Request $request, Document $project, array /** Update access time as well */ $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $key = $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } return $key; -}, ['request', 'project', 'servers', 'dbForPlatform']); +}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']); -App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request, Authorization $authorization) { $teamInternalId = ''; if ($project->getId() !== 'console') { $teamInternalId = $project->getAttribute('teamInternalId', ''); @@ -1012,7 +1022,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A if (str_starts_with($path, '/v1/projects/:projectId')) { $uri = $request->getURI(); $pid = explode('/', $uri)[3]; - $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); + $p = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); @@ -1021,7 +1031,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -1030,14 +1040,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { + $team = $authorization->skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ Query::equal('$sequence', [$teamInternalId]), ]); }); return $team; -}, ['project', 'dbForPlatform', 'utopia', 'request']); +}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']); App::setResource( 'isResourceBlocked', @@ -1075,7 +1085,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key App::setResource('executor', fn () => new Executor()); -App::setResource('resourceToken', function ($project, $dbForProject, $request) { +App::setResource('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) { $tokenJWT = $request->getParam('token'); if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication @@ -1093,7 +1103,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([]); } - $token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -1111,7 +1121,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { } return match ($token->getAttribute('resourceType')) { - TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { + TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject, $authorization) { $sequences = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); @@ -1122,7 +1132,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { $accessedAt = $token->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) { $token->setAttribute('accessedAt', DatabaseDateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); + $authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ @@ -1137,8 +1147,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { }; } return new Document([]); -}, ['project', 'dbForProject', 'request']); +}, ['project', 'dbForProject', 'request', 'authorization']); -App::setResource('transactionState', function (Database $dbForProject) { - return new TransactionState($dbForProject); -}, ['dbForProject']); +App::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) { + return new TransactionState($dbForProject, $authorization); +}, ['dbForProject', 'authorization']); diff --git a/app/realtime.php b/app/realtime.php index fab0ce7561..31e6015d92 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -32,7 +32,6 @@ 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\DSN\DSN; use Utopia\Logger\Log; use Utopia\Pools\Group; @@ -309,7 +308,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume 'value' => '{}' ]); - $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); + $statsDocument = $database->getAuthorization()->skip(fn () => $database->createDocument('realtime', $document)); break; } catch (Throwable) { Console::warning("Collection not ready. Retrying connection ({$attempts})..."); @@ -339,7 +338,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume ->setAttribute('timestamp', DateTime::now()) ->setAttribute('value', json_encode($payload)); - Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); + $database->getAuthorization()->skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (Throwable $th) { $logError($th, "updateWorkerDocument"); } @@ -370,7 +369,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $payload = []; - $list = Authorization::skip(fn () => $database->find('realtime', [ + $list = $database->getAuthorization()->skip(fn () => $database->find('realtime', [ Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)), ])); @@ -464,13 +463,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, 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 = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); /** @var Appwrite\Utopia\Database\Documents\User $user */ $user = $database->getDocument('users', $userId); - $roles = $user->getRoles(); + $roles = $user->getRoles($database->getAuthorization()); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -526,6 +525,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); + $authorization = $app->getResource('authorization'); /* * Project Check @@ -537,7 +537,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -573,7 +573,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = $user->getRoles(); + $roles = $user->getRoles($authorization); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -586,6 +586,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $realtime->subscribe($project->getId(), $connection, $roles, $channels); + $realtime->connections[$connection]['authorization'] = $authorization; + $user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ @@ -614,6 +616,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $code = 500; } + $message = $th->getMessage(); // sanitize 0 && 5xx errors @@ -643,12 +646,19 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) { try { $response = new Response(new SwooleResponse()); - $projectId = $realtime->connections[$connection]['projectId']; + $projectId = $realtime->connections[$connection]['projectId'] ?? null; + + // Get authorization from connection (stored during onOpen) + $authorization = $realtime->connections[$connection]['authorization'] ?? null; + $database = getConsoleDB(); + $database->setAuthorization($authorization); if ($projectId !== 'console') { - $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $database->getDocument('projects', $projectId)); + $database = getProjectDB($project); + $database->setAuthorization($authorization); } else { $project = null; } @@ -712,10 +722,19 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = $user->getRoles(); + $roles = $user->getRoles($database->getAuthorization()); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); + + // Preserve authorization before subscribe overwrites the connection array + $authorization = $realtime->connections[$connection]['authorization'] ?? null; + $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); + // Restore authorization after subscribe + if ($authorization !== null) { + $realtime->connections[$connection]['authorization'] = $authorization; + } + $user = $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ 'type' => 'response', diff --git a/app/worker.php b/app/worker.php index 3720fb85fe..d31e63fc8b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -49,19 +49,30 @@ use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; -Authorization::disable(); Runtime::enableCoroutine(); Server::setResource('register', fn () => $register); -Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { +Server::setResource('authorization', function () { + $authorization = new Authorization(); + $authorization->disable(); + return $authorization; +}, []); + +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, Authorization $authorization) { $pools = $register->get('pools'); $adapter = new DatabasePool($pools->get('console')); $dbForPlatform = new Database($adapter, $cache); - $dbForPlatform->setNamespace('_console'); - $dbForPlatform->setDocumentType('users', User::class); + + $dbForPlatform + ->setAuthorization($authorization) + ->setNamespace('_console') + ->setDocumentType('users', User::class) + ; + + return $dbForPlatform; -}, ['cache', 'register']); +}, ['cache', 'register', 'authorization']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -74,7 +85,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -106,15 +117,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getSequence()); } - $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database + ->setAuthorization($authorization) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform', 'authorization']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -128,7 +141,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - + $database->setAuthorization($authorization); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -165,15 +178,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf ->setNamespace('_' . $project->getSequence()); } - $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database + ->setAuthorization($authorization) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { +Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -183,6 +198,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER) @@ -195,7 +211,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day @@ -514,7 +530,8 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) { + ->inject('authorization') + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, Authorization $authorization) use ($worker, $queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); if ($logger) { @@ -530,7 +547,7 @@ $worker $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', $authorization->getRoles()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/composer.json b/composer.json index c2a3a965bd..ef833cfb38 100644 --- a/composer.json +++ b/composer.json @@ -45,14 +45,14 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.19.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "1.*.*", + "utopia-php/abuse": "1.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "2.0.2-rc3", + "utopia-php/audit": "2.*", "utopia-php/auth": "0.5.*", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", - "utopia-php/config": "1.*.*", - "utopia-php/database": "3.*.*", + "utopia-php/config": "1.*", + "utopia-php/database": "4.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.11.*", "utopia-php/emails": "0.6.*", @@ -64,7 +64,7 @@ "utopia-php/locale": "0.8.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.20.*", - "utopia-php/migration": "1.3.*", + "utopia-php/migration": "1.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 4b802b5611..20b5c754eb 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": "0644a7889caffed39ba2c9c5189e45fe", + "content-hash": "2d32f0fe31dc03c1f96a2582093afca1", "packages": [ { "name": "adhocore/jwt", @@ -3455,25 +3455,24 @@ }, { "name": "utopia-php/abuse", - "version": "1.2.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2" + "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/3339d057c6bb1fa3e5ac5b2598923f6938425ec2", - "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", + "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", "shasum": "" }, "require": { - "appwrite/appwrite": "19.*.*", "ext-curl": "*", "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "3.*.*" + "utopia-php/database": "*" }, "require-dev": { "laravel/pint": "1.*", @@ -3501,9 +3500,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/1.2.0" + "source": "https://github.com/utopia-php/abuse/tree/1.0.2" }, - "time": "2026-01-05T21:29:10+00:00" + "time": "2025-10-20T07:18:33+00:00" }, { "name": "utopia-php/analytics", @@ -3553,23 +3552,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.2-rc3", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "f60a298b516300f56a328403b334b7d62a96e7e7" + "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7", - "reference": "f60a298b516300f56a328403b334b7d62a96e7e7", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/662244bd170bab3ba45fd4470ac2e5a36c980131", + "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "3.*", + "utopia-php/database": "4.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3596,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3" + "source": "https://github.com/utopia-php/audit/tree/2.0.3" }, - "time": "2026-01-06T15:32:52+00:00" + "time": "2026-01-13T09:49:40+00:00" }, { "name": "utopia-php/auth", @@ -3899,16 +3898,16 @@ }, { "name": "utopia-php/database", - "version": "3.6.1", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7" + "reference": "783193d5cdc723b3784e8fb399068b17d4228d53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", - "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", + "url": "https://api.github.com/repos/utopia-php/database/zipball/783193d5cdc723b3784e8fb399068b17d4228d53", + "reference": "783193d5cdc723b3784e8fb399068b17d4228d53", "shasum": "" }, "require": { @@ -3951,9 +3950,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.6.1" + "source": "https://github.com/utopia-php/database/tree/4.4.0" }, - "time": "2025-12-16T09:55:41+00:00" + "time": "2026-01-08T04:54:39+00:00" }, { "name": "utopia-php/detector", @@ -4267,23 +4266,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.36", + "version": "0.33.37", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" + "reference": "30a119d76531d89da9240496940c84fcd9e1758b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", + "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", + "reference": "30a119d76531d89da9240496940c84fcd9e1758b", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4309,9 +4308,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.36" + "source": "https://github.com/utopia-php/http/tree/0.33.37" }, - "time": "2026-01-12T07:32:29+00:00" + "time": "2026-01-13T10:10:21+00:00" }, { "name": "utopia-php/image", @@ -4516,16 +4515,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.13", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715" + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/c5e3f5e970e62e8f7db97b5b90baae2af800a715", - "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", "shasum": "" }, "require": { @@ -4534,7 +4533,7 @@ "ext-openssl": "*", "php": ">=8.1", "utopia-php/console": "0.0.*", - "utopia-php/database": "3.*", + "utopia-php/database": "4.*", "utopia-php/dsn": "0.2.*", "utopia-php/storage": "0.18.*" }, @@ -4565,9 +4564,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.13" + "source": "https://github.com/utopia-php/migration/tree/1.4.3" }, - "time": "2026-01-07T14:48:05+00:00" + "time": "2026-01-13T09:51:08+00:00" }, { "name": "utopia-php/mongo", @@ -5057,22 +5056,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.6", + "version": "0.8.4", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.36" + "utopia-php/framework": "0.33.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5102,9 +5101,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.6" + "source": "https://github.com/utopia-php/swoole/tree/0.8.4" }, - "time": "2026-01-12T07:57:35+00:00" + "time": "2025-09-07T09:39:46+00:00" }, { "name": "utopia-php/system", @@ -5214,16 +5213,16 @@ }, { "name": "utopia-php/validators", - "version": "0.1.0", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", "shasum": "" }, "require": { @@ -5231,7 +5230,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", + "phpstan/phpstan": "2.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5253,9 +5252,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.1.0" + "source": "https://github.com/utopia-php/validators/tree/0.2.0" }, - "time": "2025-11-18T11:05:46+00:00" + "time": "2026-01-13T09:16:51+00:00" }, { "name": "utopia-php/vcs", @@ -8988,9 +8987,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/audit": 5 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -9014,5 +9011,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 23dc6fc2e9..8e098774e6 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -20,10 +20,12 @@ use Utopia\Database\Validator\Authorization; class TransactionState { private Database $dbForProject; - - public function __construct(Database $dbForProject) + private Authorization $authorization; + /** @var Authorization $authorization */ + public function __construct(Database $dbForProject, Authorization $authorization) { $this->dbForProject = $dbForProject; + $this->authorization = $authorization; } @@ -342,12 +344,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + $transaction = $this->authorization->skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') { return []; } - $operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [ + $operations = $this->authorization->skip(fn () => $this->dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index bc37924db6..ea51225ba6 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -100,8 +100,6 @@ abstract class Migration public function __construct() { - Authorization::disable(); - Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -129,6 +127,7 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -136,6 +135,9 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; + $authorization->disable(); + $authorization->setDefaultStatus(false); + return $this; } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index 1ff2f8f706..bf7d01764f 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -21,7 +21,7 @@ class Action extends PlatformAction return \dirname(__DIR__, 6); } - protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response): void + protected function avatar(string $type, string $code, int $width, int $height, int $quality, Response $response): void { $code = \strtolower($code); $type = \strtolower($type); @@ -58,10 +58,10 @@ class Action extends PlatformAction unset($image); } - protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger): array + protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array { try { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -112,7 +112,7 @@ class Action extends PlatformAction ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); + $authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -120,7 +120,7 @@ class Action extends PlatformAction do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php index 04648752b5..637ea647ef 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('browsers', $code, $width, $height, $quality, $response); + $this->avatar('browsers', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index 1c0de4001e..a6a013ef21 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -68,7 +69,7 @@ class Get extends Action $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index 9d53991dd6..f8e7a35b05 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -69,7 +70,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index f7c983db78..37776a3466 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -73,7 +74,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php index 5d3429b377..87357f14c7 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('credit-cards', $code, $width, $height, $quality, $response); + $this->avatar('credit-cards', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php index c3960c134e..8230b15f50 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('flags', $code, $width, $height, $quality, $response); + $this->avatar('flags', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 47afc90986..33b69dd589 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -13,6 +13,7 @@ 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\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; @@ -142,7 +143,7 @@ class Base extends Action return $deployment; } - public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document + public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = ''): Document { $deploymentId = ID::unique(); $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); @@ -239,7 +240,7 @@ class Base extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -265,7 +266,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -302,7 +303,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -328,6 +329,8 @@ class Base extends Action } } + $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) @@ -336,4 +339,34 @@ class Base extends Action return $deployment; } + + /** + * Update empty manual rule for deployment. + * In case of first deployment, deployment ID will be empty in the rules, so we need to update it here. + * + * @param \Utopia\Database\Document $project + * @param \Utopia\Database\Document $resource + * @param \Utopia\Database\Document $deployment + * @param \Utopia\Database\Database $dbForPlatform + * @return void + */ + public static function updateEmptyManualRule(Document $project, Document $resource, Document $deployment, Database $dbForPlatform, Authorization $authorization) + { + $resourceType = $resource->getCollection() === 'sites' ? 'site' : 'function'; + + $queries = [ + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), + Query::equal('deploymentResourceType', [$resourceType]), + Query::equal('deploymentId', ['']), + Query::equal('type', ['deployment']), + Query::equal('trigger', ['manual']), + ]; + $dbForPlatform->forEach('rules', function (Document $rule) use ($deployment, $dbForPlatform, $authorization) { + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([ + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getSequence(), + ]))); + }, $queries); + } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index aa43b12125..1468bf71ac 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -60,6 +60,7 @@ class Get extends Action ->inject('response') ->inject('dbForPlatform') ->inject('platform') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,7 +69,8 @@ class Get extends Action string $type, Response $response, Database $dbForPlatform, - array $platform + array $platform, + Authorization $authorization, ) { $domains = $platform['hostnames'] ?? []; if ($type === 'rules') { @@ -121,7 +123,7 @@ class Get extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $document = $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$value]), ])); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 83a401a35e..e2df5d92e6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -292,7 +292,7 @@ abstract class Action extends UtopiaAction }; } - protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document + protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): Document { $key = $attribute->getAttribute('key'); $type = $attribute->getAttribute('type', ''); @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException(), params: [$type]); } - $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, params: [$databaseId]); @@ -371,7 +371,7 @@ abstract class Action extends UtopiaAction \in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) && $attribute->getAttribute('required') ) { - $hasData = !Authorization::skip(fn () => $dbForProject + $hasData = !$authorization->skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -472,9 +472,9 @@ abstract class Action extends UtopiaAction return $attribute; } - protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document + protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index f04532aeee..442461fdd3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -81,7 +83,7 @@ class Create extends Action 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 003b4227c9..92324aae70 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -68,10 +69,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -79,6 +81,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_BOOLEAN, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index c2982445a4..bd3108a871 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index 984d4b0245..2518875424 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_DATETIME, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 649cde10aa..37ae2a7bfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -67,12 +67,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index b36072eb75..a36e264e50 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 382f16b469..609a337625 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_EMAIL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 9145191b0c..3c47d1fdfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -73,10 +74,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { if (!is_null($default) && !\in_array($default, $elements, true)) { throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); @@ -98,7 +100,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 2f47eb0cc6..5bea5230c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_ENUM, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 56d8874794..0dc11bd76c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,10 +75,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $min ??= -PHP_FLOAT_MAX; $max ??= PHP_FLOAT_MAX; @@ -100,7 +102,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 330c649f27..20b5c0767d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_FLOAT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 3a8eece531..436b22c6c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -68,12 +68,13 @@ class Get extends Action ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 2340d1d55d..2adf3977f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index 236dbf7f83..eccf18b005 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_IP, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 30f58097ce..58ded9b78a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,10 +75,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $min ??= \PHP_INT_MIN; $max ??= \PHP_INT_MAX; @@ -102,7 +104,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 67c371c69d..84a43018d1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_INTEGER, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index f0fd728902..fc846957b0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_LINESTRING, 'required' => $required, 'default' => $default - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 3407da2b34..8fff545921 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_LINESTRING, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index f2e4d19267..a89c21581d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POINT, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index 86e78e56e3..9561fe6b96 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_POINT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 4c49b21050..54da3ac604 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POLYGON, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index 0dbb117cec..b82a3d4be0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_POLYGON, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index b43568a968..615e64dfd7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -83,16 +83,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $key ??= $relatedCollectionId; $twoWayKeyWasProvided = $twoWayKey !== null; $twoWayKey ??= $collectionId; - $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, params: [$databaseId]); } @@ -154,7 +155,7 @@ class Create extends Action 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, ] - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); foreach ($attribute->getAttribute('options', []) as $k => $option) { $attribute->setAttribute($k, $option); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index feed58a4ff..d180131a44 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,6 +72,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -82,7 +84,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -90,6 +93,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_RELATIONSHIP, required: false, options: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index b42558f063..b3fe03cace 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -77,6 +78,7 @@ class Create extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -93,7 +95,8 @@ class Create extends Action Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, - array $plan + array $plan, + Authorization $authorization ): void { if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.'); @@ -132,7 +135,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $attribute->setAttribute('encrypt', $encrypt); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 53ea2a0e03..37547f3da8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,6 +73,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -85,7 +87,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -93,6 +96,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, size: $size, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index 7529845016..ed1a23acf5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,6 +71,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -83,7 +85,8 @@ class Create extends Action UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -93,7 +96,7 @@ class Create extends Action 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 9ba8ebb859..08f7a26fd9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,6 +70,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -81,7 +83,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( $databaseId, @@ -89,6 +92,7 @@ class Update extends Action $key, $dbForProject, $queueForEvents, + $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_URL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 6bfe5f8913..61c5b295cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -64,12 +64,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 724f40f00e..89cc14056a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -85,12 +85,13 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index af36649061..fd2c419954 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -64,12 +64,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index f16d00998d..ec65135a05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -258,9 +258,9 @@ abstract class Action extends DatabasesAction Document $collection, Document $document, Database $dbForProject, - /* options */ array &$collectionsCache, + Authorization $authorization, ?int &$operations = null, ): bool { @@ -297,7 +297,7 @@ abstract class Action extends DatabasesAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = Authorization::skip( + $relatedCollectionDoc = $authorization->skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId @@ -323,7 +323,8 @@ abstract class Action extends DatabasesAction document: $relation, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations + operations: $operations, + authorization: $authorization ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 53831f0fc5..16b7bd1b25 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -85,20 +85,21 @@ class Decrement extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $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, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -106,7 +107,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index ea680db3b1..7adae7633b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -85,20 +85,21 @@ class Increment extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $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, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -106,7 +107,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6ec06f5c8a..bbc63da499 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -24,6 +24,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -132,9 +133,10 @@ class Create extends Action ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void { $data = \is_string($data) ? \json_decode($data, true) @@ -178,19 +180,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -204,7 +206,7 @@ class Create extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext()); } - $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, @@ -247,8 +249,8 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + if (!$authorization->hasRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')'); } } } @@ -259,21 +261,25 @@ class Create extends Action $operations = 0; - $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations) { + $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations, $authorization) { $operations++; $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validator = new Authorization($permission); - $valid = $validator->isValid($collection->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + $validCollection = $authorization->isValid( + new Input($permission, $collection->getPermissionsByType($permission)) + ); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($document->getUpdate()); + $validDocument = $authorization->isValid( + new Input($permission, $document->getUpdate()) + ); + $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } } @@ -298,7 +304,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -314,7 +320,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = Authorization::skip( + $current = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -369,7 +375,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -468,6 +474,7 @@ class Create extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index faae638c88..7acf8e386e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -83,6 +83,7 @@ class Delete extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,18 +98,19 @@ class Delete extends Action Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, - array $plan + array $plan, + Authorization $authorization ): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -121,7 +123,7 @@ class Delete extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -131,7 +133,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -205,6 +207,7 @@ class Delete extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index f560267d4b..cb8b0dd42e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -70,20 +70,21 @@ class Get extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -125,6 +126,7 @@ class Get extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization, operations: $operations ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index a4dd38ef67..2f5579f0ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -72,13 +72,14 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 707857347a..a92d8ec180 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -87,10 +87,11 @@ class Update extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -98,16 +99,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -125,7 +126,7 @@ class Update extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -140,7 +141,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -153,7 +154,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -171,7 +172,7 @@ class Update extends Action $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { $operations++; $relationships = \array_filter( @@ -195,7 +196,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -212,7 +213,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -249,7 +250,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -340,6 +341,7 @@ class Update extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization, ); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index b32871add2..62e59dd010 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -91,10 +91,11 @@ class Upsert extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -106,15 +107,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -139,7 +140,7 @@ class Upsert extends Action // Use transaction-aware document retrieval to see changes from same transaction $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -155,7 +156,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -168,7 +169,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -181,7 +182,7 @@ class Upsert extends Action $newDocument = new Document($data); $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { $operations++; $relationships = \array_filter( @@ -205,7 +206,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -222,7 +223,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -259,7 +260,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -361,6 +362,7 @@ class Upsert extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); $relationships = \array_map( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 8b770284c3..ff94e67b02 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -74,20 +74,21 @@ class XList extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -115,7 +116,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); @@ -161,7 +162,8 @@ class XList extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations, + authorization: $authorization, + operations: $operations ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index e7909772a5..d8df8f1f8c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -57,12 +57,13 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 872b7348fe..5b035a8688 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -79,12 +79,13 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 27b28e866c..d9f9f66504 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -70,12 +70,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index d66bf8f38f..661f259910 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -59,12 +59,13 @@ class Get extends Action ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index abbdefb4d5..90826ffbe3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -66,13 +66,14 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { /** @var Document $database */ - $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, params: [$databaseId]); @@ -112,7 +113,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = $authorization->skip(fn () => $dbForProject->find('indexes', [ Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 0f5a57c6e9..0b6e47a798 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -71,13 +71,14 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void { - $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, params: [$databaseId]); @@ -112,9 +113,9 @@ class XList extends Action $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); + $os = $detector->getOS() ?: []; + $client = $detector->getClient() ?: []; + $device = $detector->getDevice() ?: []; $output[$i] = new Document([ 'event' => $log['event'], @@ -122,20 +123,20 @@ class XList extends Action 'userEmail' => $log['data']['userEmail'] ?? null, 'userName' => $log['data']['userName'] ?? null, 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'ip' => $log['ip'] ?? null, + 'time' => $log['time'] ?? null, + 'osCode' => $os['osCode'] ?? null, + 'osName' => $os['osName'] ?? null, + 'osVersion' => $os['osVersion'] ?? null, + 'clientType' => $client['clientType'] ?? null, + 'clientCode' => $client['clientCode'] ?? null, + 'clientName' => $client['clientName'] ?? null, + 'clientVersion' => $client['clientVersion'] ?? null, + 'clientEngine' => $client['clientEngine'] ?? null, + 'clientEngineVersion' => $client['clientEngineVersion'] ?? null, + 'deviceName' => $device['deviceName'] ?? null, + 'deviceBrand' => $device['deviceBrand'] ?? null, + 'deviceModel' => $device['deviceModel'] ?? null ]); $record = $geodb->get($log['ip']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index e319a33e67..304ce5c88e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -71,12 +71,13 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index c4a46650c9..0552a31509 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -63,10 +63,11 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); @@ -83,7 +84,7 @@ class Get extends Action str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index b0b0385bf5..c23286f3cd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -67,12 +67,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php index 20c71223c6..4ca20f8414 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -55,10 +55,11 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('authorization') ->callback($this->action(...)); } - public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user): void + public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, Authorization $authorization): void { $permissions = []; if (!empty($user->getId())) { @@ -73,7 +74,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ + $transaction = $authorization->skip(fn () => $dbForProject->createDocument('transactions', new Document([ '$id' => ID::unique(), '$permissions' => $permissions, 'status' => 'pending', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php index 5a2568db0c..f09ed2bc27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -18,6 +18,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -63,21 +64,22 @@ class Create extends Action ->inject('dbForProject') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan): void + public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization): void { if (empty($operations)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -113,13 +115,13 @@ class Create extends Action throw new Exception(Exception::USER_UNAUTHORIZED); } - $database = $databases[$operation['databaseId']] ??= Authorization::skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); + $database = $databases[$operation['databaseId']] ??= $authorization->skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$operation['databaseId']]); } $collection = $collections[$operation[$this->getGroupId()]] ??= - Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND, params: [$operation[$this->getGroupId()]]); @@ -165,14 +167,20 @@ class Create extends Action // For individual operations, enforce permissions unless using API key/admin if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validator = new Authorization($permissionType); - $collectionValid = $validator->isValid($collection->getPermissionsByType($permissionType)); + + $collectionValid = $authorization->isValid( + new Input($permissionType, $collection->getPermissionsByType($permissionType)) + ); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $validator->isValid($document->getUpdate()); + $documentValid = $authorization->isValid( + new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) + ); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $validator->isValid($document->getDelete()); + $documentValid = $authorization->isValid( + new Input(Database::PERMISSION_DELETE, $document->getDelete()) + ); } } @@ -189,7 +197,7 @@ class Create extends Action // Users can only set permissions for roles they have if (isset($operation['data']['$permissions'])) { $permissions = $operation['data']['$permissions']; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -201,7 +209,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -230,7 +238,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { $dbForProject->createDocuments('transactionLogs', $staged); return $dbForProject->increaseDocumentAttribute( 'transactions', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php index 9235c81b8e..e4f1051464 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -76,6 +76,7 @@ class Update extends Action ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('authorization') ->callback($this->action(...)); } @@ -102,7 +103,7 @@ class Update extends Action * @throws Structure * @throws \Utopia\Exception */ - public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void + public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization): void { if (!$commit && !$rollback) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); @@ -111,11 +112,11 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -138,12 +139,12 @@ class Update extends Action $currentDocumentId = null; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) { + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -167,7 +168,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = Authorization::skip( + $collections[$collectionId] = $authorization->skip( fn () => $dbForProject->getCollection($collectionId) ); } @@ -232,7 +233,7 @@ class Update extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -243,33 +244,33 @@ class Update extends Action ->setDocument($transaction); }); } catch (NotFoundException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e, params: [$currentDocumentId ?? 'unknown']); } catch (DuplicateException | ConflictException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_CONFLICT, previous: $e); } catch (StructureException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (LimitException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, $e->getMessage()); } catch (TransactionException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_FAILED, $e->getMessage()); } catch (QueryException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); @@ -297,11 +298,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ + $database = $authorization->skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = $authorization->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -393,7 +394,7 @@ class Update extends Action } if ($rollback) { - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'failed']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index a717b00ae4..a1aa7a70b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -59,10 +59,11 @@ class Get extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); @@ -81,7 +82,7 @@ class Get extends Action str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index c13149cfc7..757f845c68 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -56,10 +56,11 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, UtopiaResponse $response, Database $dbForProject): void + public function action(string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $periods = Config::getParam('usage', []); @@ -74,7 +75,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php index c0d502d10a..eede1b221b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php @@ -60,6 +60,7 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php index c5939b6974..cd8d392cfc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php @@ -61,6 +61,7 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php index 63693abb67..79722efee1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php @@ -62,6 +62,7 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php index b022d0ed85..c39681a743 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php @@ -63,6 +63,7 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php index 8a691a6e98..da63b0cef7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php @@ -58,6 +58,7 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php index 6d19f99b7b..51e7f295a1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php @@ -61,6 +61,7 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php index 48a04304bd..daca13d587 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php @@ -62,6 +62,7 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php index bd280a2910..4d5881c81e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php @@ -64,6 +64,7 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php index ac5c1cf907..122671adc5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php @@ -65,6 +65,7 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php index 8293d66992..cd898fa0bf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php @@ -63,6 +63,7 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php index bf2815db45..ee9c5f6cb1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php @@ -64,6 +64,7 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php index ee88ac8683..39dafbd1a6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php @@ -61,6 +61,7 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php index 9b38cd9dfd..80c764b4c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php @@ -61,6 +61,7 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php index 7db8625ebf..54ed029c71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php @@ -62,6 +62,7 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index e0ed059681..45e0cc6f60 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -63,6 +63,7 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index 7afc239201..f1f4ebb4a9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -64,6 +64,7 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php index 6110d6ee07..227fece7de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php @@ -61,6 +61,7 @@ class Create extends LineCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php index afd0098152..b0e433da5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php @@ -63,6 +63,7 @@ class Update extends LineUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php index 084adca860..3fc5865905 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php @@ -61,6 +61,7 @@ class Create extends PointCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 632be85871..040b8171d7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php @@ -63,6 +63,7 @@ class Update extends PointUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php index 723940af58..630340ba7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php @@ -61,6 +61,7 @@ class Create extends PolygonCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 91b55f74b4..43b4a4e6a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php @@ -63,6 +63,7 @@ class Update extends PolygonUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php index f3933160c0..7f28a3cdb7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php @@ -73,6 +73,7 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index eb87713457..fd7fdab8de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php @@ -65,6 +65,7 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php index 9279409e88..ff50313a7c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php @@ -66,6 +66,7 @@ class Create extends StringCreate ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 9fffa71b33..6ad1be124b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php @@ -65,6 +65,7 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php index 50f5ea5d5b..b19d6e80a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php @@ -61,6 +61,7 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index b52ea66ce1..dce11964e8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php @@ -62,6 +62,7 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 39551e5113..13ebe14682 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -52,6 +52,7 @@ class XList extends AttributesXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php index 7287c2cb3e..bd08ad5617 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -67,6 +67,7 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php index d4af8b3508..925a7b2494 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php @@ -55,6 +55,7 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php index 4286ee07ca..ad83291815 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php @@ -50,6 +50,7 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index 727334b6da..09720f4d71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php @@ -66,6 +66,8 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } + } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php index 7d187ab5a1..7fa8073d1e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php @@ -61,6 +61,7 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php index 75ee507aa8..246d569825 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php @@ -52,6 +52,7 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index bf5f27e388..1dc2d3ea43 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -54,6 +54,7 @@ class XList extends IndexXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php index 5eab050b7e..79691436e4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php @@ -50,6 +50,7 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php index accb0392fe..b9896d282d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php @@ -66,6 +66,7 @@ class Delete extends DocumentsDelete ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php index fea59b8b13..f4ccea1698 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php @@ -68,6 +68,7 @@ class Update extends DocumentsUpdate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php index 492af25e9f..69a687d92f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php @@ -68,6 +68,7 @@ class Upsert extends DocumentsUpsert ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php index 42f2919ce1..a660b008e1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php @@ -67,6 +67,7 @@ class Decrement extends DecrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php index 3d04d71c26..c2b69429ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php @@ -67,6 +67,7 @@ class Increment extends IncrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php index b5491a593b..c70ed71378 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php @@ -111,6 +111,7 @@ class Create extends DocumentCreate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php index bcd8682a48..1763491c19 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php @@ -70,6 +70,7 @@ class Delete extends DocumentDelete ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php index 450fb4d746..bb24e93de0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php @@ -58,6 +58,7 @@ class Get extends DocumentGet ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php index 27bd82195d..86bfcfec85 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php @@ -51,6 +51,7 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php index fe4ffc4995..0879055a78 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php @@ -69,6 +69,7 @@ class Update extends DocumentUpdate ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index 0fbaa921cb..99e0487c93 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -72,6 +72,7 @@ class Upsert extends DocumentUpsert ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index c51017fa75..230d391110 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -59,6 +59,7 @@ class XList extends DocumentXList ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php index 03316783cd..0d3bc9afc1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -62,6 +62,7 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php index 0fb44ee94a..b8be7edd56 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php @@ -52,6 +52,7 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index e0c590379b..5532203d0a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -55,6 +55,7 @@ class XList extends CollectionXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php index 27454664f4..e7e5f0132f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php @@ -50,6 +50,7 @@ class Create extends TransactionsCreate ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php index 4668ae2d15..1228c83e30 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php @@ -54,6 +54,7 @@ class Create extends OperationsCreate ->inject('dbForProject') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php index 4337a8d28d..8be28ce9f7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php @@ -60,6 +60,7 @@ class Update extends TransactionsUpdate ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php index 89b9fbd8c2..87be8a9eab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php @@ -48,6 +48,7 @@ class Get extends DatabaseUsageGet ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php index 0bd96fc40a..2cde337f5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php @@ -46,6 +46,7 @@ class XList extends DatabaseUsageXList ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index e7e34d4c5b..c5ae08728d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -17,6 +17,7 @@ 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\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -88,6 +89,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -105,7 +107,8 @@ class Create extends Action Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index 0aaea3bd4a..acfaa965ac 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -15,6 +15,7 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -77,6 +78,7 @@ class Create extends Base ->inject('project') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -95,7 +97,8 @@ class Create extends Base Event $queueForEvents, Document $project, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -127,7 +130,9 @@ class Create extends Base queueForBuilds: $queueForBuilds, template: $template, github: $github, - activate: $activate + activate: $activate, + referenceType: $type, + reference: $reference ); $queueForEvents @@ -170,6 +175,9 @@ class Create extends Base ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); + + $this->updateEmptyManualRule($project, $function, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php index 69594c3d86..25dce63b38 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -87,7 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, ) { $function = $dbForProject->getDocument('functions', $functionId); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 81f55ba829..1a265298d3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -29,6 +29,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -99,6 +100,7 @@ class Create extends Base ->inject('proofForToken') ->inject('executor') ->inject('platform') + ->inject('authorization') ->callback($this->action(...)); } @@ -123,7 +125,8 @@ class Create extends Base Store $store, Token $proofForToken, Executor $executor, - array $platform + array $platform, + Authorization $authorization, ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -161,10 +164,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -180,7 +183,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); @@ -194,10 +197,8 @@ class Create extends Base throw new Exception(Exception::BUILD_NOT_READY); } - $validator = new Authorization('execute'); - - if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + if (!$authorization->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $jwt = ''; // initialize @@ -295,7 +296,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -336,7 +337,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -488,7 +489,7 @@ class Create extends Base ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index 9a93e5a342..c7a9a6d330 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -61,6 +61,7 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Delete extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -108,7 +110,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 6bd0a3675e..c5eebe139e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -52,6 +52,7 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -59,12 +60,13 @@ class Get extends Base string $functionId, string $executionId, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 20680e87ff..ff381e1f3d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -60,6 +60,7 @@ class XList extends Base ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,12 +69,13 @@ class XList extends Base array $queries, bool $includeTotal, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index 5c226c5925..6ad488283e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -115,6 +115,7 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -152,7 +153,8 @@ class Create extends Base Func $queueForFunctions, Database $dbForPlatform, Request $request, - GitHub $github + GitHub $github, + Authorization $authorization ) { // Temporary abuse check @@ -237,7 +239,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = Authorization::skip( + $schedule = $authorization->skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -315,6 +317,7 @@ class Create extends Base template: $template, github: $github, activate: true, + authorization: $authorization, reference: $providerBranch, referenceType: 'branch' ); @@ -366,7 +369,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $rule = Authorization::skip( + $rule = $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index dfa6636554..9cafc17bbe 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -61,6 +61,7 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Delete extends Base Database $dbForProject, DeleteEvent $queueForDeletes, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -87,7 +89,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index b6dcfd6cf8..aeccf98a02 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -62,6 +62,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,7 +73,8 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -101,7 +103,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -112,12 +114,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index adb29bc533..55c5b30418 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -104,6 +104,7 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') + ->inject('authorization') ->callback($this->action(...)); } @@ -134,7 +135,8 @@ class Update extends Base Build $queueForBuilds, Database $dbForPlatform, GitHub $github, - Executor $executor + Executor $executor, + Authorization $authorization ) { // TODO: If only branch changes, re-deploy $function = $dbForProject->getDocument('functions', $functionId); @@ -282,7 +284,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents->setParam('functionId', $function->getId()); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index acb6995d6f..1fa65d0cc9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -55,10 +55,11 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $functionId, string $range, Response $response, Database $dbForProject) + public function action(string $functionId, string $range, Response $response, Database $dbForProject, Authorization $authorization) { $function = $dbForProject->getDocument('functions', $functionId); @@ -83,7 +84,7 @@ class Get extends Base str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index 6a4ded4db7..38a95d4469 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -52,10 +52,11 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -75,7 +76,7 @@ class XList extends Base str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 815f1bd8fc..5438479d40 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -65,6 +65,7 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -76,7 +77,8 @@ class Create extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Document $project + Document $project, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -119,7 +121,7 @@ class Create extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 50c1de4232..161eed3112 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -57,6 +57,7 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -65,7 +66,8 @@ class Delete extends Base string $variableId, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -92,7 +94,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 5c1f5809cd..6af5ac90c2 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -62,6 +62,7 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -73,7 +74,8 @@ class Update extends Base ?bool $secret, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -110,7 +112,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 414696306f..8f041dd57b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -25,7 +25,6 @@ use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Detector\Detection\Rendering\SSR; use Utopia\Detector\Detection\Rendering\XStatic; use Utopia\Detector\Detector\Rendering; @@ -1121,7 +1120,7 @@ class Builds extends Action ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $resource->getAttribute('schedule')) ->setAttribute('active', !empty($resource->getAttribute('schedule')) && !empty($resource->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } Console::info('Deployment action finished'); @@ -1350,7 +1349,6 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception - * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1439,11 +1437,11 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $rule = $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal("deploymentInternalId", [$deployment->getSequence()]), - ])); + ]); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $previewUrl = match($resource->getCollection()) { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 4ba51bca37..3de0322d6e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -87,6 +87,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -106,7 +107,8 @@ class Create extends Action Device $deviceForSites, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -276,7 +278,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -341,7 +343,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -366,6 +368,8 @@ class Create extends Action } } + + $metadata = null; $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 2f9b1bdfde..9554e2aa14 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -65,6 +65,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') + ->inject('authorization') ->callback($this->action(...)); } @@ -78,7 +79,8 @@ class Create extends Action Database $dbForPlatform, Event $queueForEvents, Build $queueForBuilds, - Device $deviceForSites + Device $deviceForSites, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -147,7 +149,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 5f1d446809..30d5e779c1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -79,6 +79,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,7 +98,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -130,6 +132,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, ); $queueForEvents @@ -189,7 +192,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -209,6 +212,8 @@ class Create extends Base ])) ); + $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index 915e3c5c9f..feff28427e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -72,6 +73,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -87,7 +89,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -110,6 +113,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, reference: $reference, referenceType: $type ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index f962d0118d..b5d956128b 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -60,6 +60,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -104,12 +106,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index af96c10457..5c274d6a20 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -55,6 +55,7 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -62,7 +63,8 @@ class Get extends Base string $siteId, string $range, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -91,7 +93,7 @@ class Get extends Base ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index d36cc56ae5..a90cb0cab9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -52,10 +52,11 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -78,7 +79,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index ed5c23b6c1..4757461a98 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -22,6 +22,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -90,6 +91,7 @@ class Create extends Action ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') + ->inject('authorization') ->callback($this->action(...)); } @@ -105,26 +107,26 @@ class Create extends Action Event $queueForEvents, string $mode, Device $deviceForFiles, - Device $deviceForLocal + Device $deviceForLocal, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $allowedPermissions = [ - \Utopia\Database\Database::PERMISSION_READ, - \Utopia\Database\Database::PERMISSION_UPDATE, - \Utopia\Database\Database::PERMISSION_DELETE, + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, ]; // Map aggregate permissions to into the set of individual permissions they represent. @@ -141,7 +143,7 @@ class Create extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser) { foreach (\Utopia\Database\Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -154,7 +156,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -379,11 +381,10 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } // Trigger after create success hook @@ -427,13 +428,12 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index eccacaafd2..ca376842e2 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -64,6 +65,7 @@ class Delete extends Action ->inject('queueForEvents') ->inject('deviceForFiles') ->inject('queueForDeletes') + ->inject('authorization') ->callback($this->action(...)); } @@ -75,33 +77,33 @@ class Delete extends Action Event $queueForEvents, Device $deviceForFiles, DeleteEvent $queueForDeletes, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_DELETE); - $valid = $validator->isValid($bucket->getDelete()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $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())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if ($fileSecurity && !$valid && !$authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $deviceDeleted = false; @@ -125,7 +127,7 @@ class Delete extends Action if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = $authorization->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index 45e3b83375..bbceff51ec 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -68,6 +69,7 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -80,13 +82,14 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization, ) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -94,17 +97,16 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index 77f163e5fb..caaab29efc 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -10,6 +10,7 @@ use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -49,6 +50,7 @@ class Get extends Action ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -57,27 +59,27 @@ class Get extends Action string $fileId, Response $response, Database $dbForProject, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 9c4e49d0bb..7ab3e713bc 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -17,6 +17,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Image\Image; use Utopia\Platform\Action; @@ -90,6 +91,7 @@ class Get extends Action ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -114,7 +116,8 @@ class Get extends Action Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, - Document $project + Document $project, + Authorization $authorization ) { if (!\extension_loaded('imagick')) { @@ -122,10 +125,10 @@ class Get extends Action } /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -137,17 +140,16 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -269,11 +271,11 @@ class Get extends Action $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php index 67372435b1..516343e23f 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('project') ->inject('mode') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -64,7 +65,8 @@ class Get extends Action Database $dbForPlatform, Document $project, string $mode, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization ) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -86,15 +88,15 @@ class Get extends Action $disposition = $decoded['disposition'] ?? 'inline'; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index be78cc358b..57856c1564 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -14,6 +14,7 @@ use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -62,6 +63,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,26 +74,26 @@ class Update extends Action ?array $permissions, Response $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $valid = $validator->isValid($bucket->getUpdate()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -105,7 +107,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -118,7 +120,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -139,7 +141,7 @@ class Update extends Action if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index 41ee95b165..3874fedacf 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -15,6 +15,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -69,6 +70,7 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -81,13 +83,14 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization ) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -95,17 +98,16 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index e46fdb2a0a..3663b56fab 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -16,6 +16,7 @@ use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -61,6 +62,7 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('mode') + ->inject('authorization') ->callback($this->action(...)); } @@ -71,22 +73,22 @@ class XList extends Action bool $includeTotal, Response $response, Database $dbForProject, - string $mode + string $mode, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } try { @@ -119,7 +121,7 @@ class XList extends Action if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -136,8 +138,8 @@ class XList extends Action $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $includeTotal ? Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; + $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $includeTotal ? $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php index 5c3515122b..4e75de27c8 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } @@ -59,7 +60,8 @@ class Get extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB + callable $getLogsDB, + Authorization $authorization, ): void { $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -75,19 +77,20 @@ class Get extends Action $statsDocId = md5('_inf_' . $metric); - $dbForLogs = call_user_func($getLogsDB, $project); - $storageStats = Authorization::skip( - fn () => $dbForLogs->getDocument( + $totalSize = 0; + + try { + $dbForLogs = $getLogsDB($project); + $storageStats = $authorization->skip(fn () => $dbForLogs->getDocument( 'stats', $statsDocId, [Query::select(['value'])] - ) - ); + )); - /** - * The value can be 0 if stats were not aggregated when this request was made! - */ - $totalSize = $storageStats->isEmpty() ? 0 : $storageStats->getAttribute('value', 0); + $totalSize = $storageStats->getAttribute('value', 0); + } catch (\Throwable) { + // Stats may not be available, default to 0 + } $bucket->setAttribute('totalSize', $totalSize); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php index a2c880ce08..601d9b5321 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php @@ -58,6 +58,7 @@ class XList extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,7 +69,8 @@ class XList extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB + callable $getLogsDB, + Authorization $authorization ) { try { $queries = Query::parseQueries($queries); @@ -117,7 +119,6 @@ class XList extends Action if (!empty($buckets)) { $bucketByStatsId = []; - $dbForLogs = call_user_func($getLogsDB, $project); foreach ($buckets as $bucket) { $metric = str_replace( @@ -134,22 +135,28 @@ class XList extends Action $bucket->setAttribute('totalSize', 0); } - /* @type Document[] $stats */ - $stats = Authorization::skip(function () use ($dbForLogs, $bucketByStatsId) { - $statsIds = array_keys($bucketByStatsId); + try { + $dbForLogs = $getLogsDB($project); - return $dbForLogs->find('stats', [ - Query::equal('$id', $statsIds), - Query::select(['value']), - ]); - }); + /* @var array $stats */ + $stats = $authorization->skip(function () use ($dbForLogs, $bucketByStatsId) { + $statsIds = array_keys($bucketByStatsId); - foreach ($stats as $stat) { - $bucket = $bucketByStatsId[$stat->getId()]; + return $dbForLogs->find('stats', [ + Query::equal('$id', $statsIds), + Query::select(['value']), + ]); + }); - if ($bucket) { - $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); + foreach ($stats as $stat) { + $bucket = $bucketByStatsId[$stat->getId()]; + + if ($bucket) { + $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); + } } + } catch (\Throwable) { + // Stats may not be available, default to 0 } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php index b816e83f72..a7bda355da 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php @@ -54,10 +54,11 @@ class Get extends Action ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) + public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, Authorization $authorization) { $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -75,7 +76,7 @@ class Get extends Action str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php index d29fa7c1b4..44fdd54e8c 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php @@ -49,10 +49,11 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -63,7 +64,7 @@ class XList extends Action METRIC_FILES_STORAGE, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index f79dece530..5f1bd55788 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -6,32 +6,31 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Documents\User; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; class Action extends UtopiaAction { - protected function getFileAndBucket(Database $dbForProject, string $bucketId, string $fileId): array + protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, string $bucketId, string $fileId): array { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); - if (!$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 3d1f6eef38..6cbaeaa915 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -14,6 +14,7 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -65,23 +66,23 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { /** * @var Document $bucket * @var Document $file */ - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $bucketPermission = $validator->isValid($bucket->getUpdate()); + $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if ($fileSecurity) { - $filePermission = $validator->isValid($file->getUpdate()); + $filePermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); if (!$bucketPermission && !$filePermission) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 8a9301713b..13da92cbc6 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -13,6 +13,7 @@ use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; @@ -57,12 +58,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) + public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization) { - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 3e35c1c1fa..cc6981fa1b 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -31,6 +31,7 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') + ->inject('authorisation') ->callback($this->action(...)); } @@ -47,8 +48,8 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, + Authorization $authorization ): void { - Authorization::disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); @@ -66,14 +67,14 @@ class Migrate extends Action $count = 0; $total = $dbForPlatform->count('projects') + 1; - $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total, $authorization) { /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); $dbForProject->disableValidation(); try { $migration - ->setProject($project, $dbForProject, $dbForPlatform, $getProjectDB) + ->setProject($project, $dbForProject, $dbForPlatform, $authorization, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -88,7 +89,7 @@ class Migrate extends Action try { $migration - ->setProject($console, $getProjectDB($console), $dbForPlatform, $getProjectDB) + ->setProject($console, $getProjectDB($console), $dbForPlatform, $authorization, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 9698fe9034..19ed3bc099 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -8,7 +8,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; @@ -61,7 +60,7 @@ abstract class ScheduleBase extends Action $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $dbForPlatform->updateDocument('projects', $project->getId(), $project); } } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index b64dd61f86..6d04d2109a 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -8,7 +8,6 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\System\System; /** @@ -61,9 +60,7 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue) { - Authorization::disable(); - Authorization::setDefaultStatus(false); + Console::loop(function () use ($queue, $dbForPlatform) { $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); /** diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 5132687279..33ebd39092 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -21,6 +21,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -58,6 +59,7 @@ class Certificates extends Action ->inject('log') ->inject('certificates') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,6 +74,8 @@ class Certificates extends Action * @param Certificate $queueForCertificates * @param Log $log * @param CertificatesAdapter $certificates + * @param array $plan + * @param ValidatorAuthorization $authorization * @return void * @throws Throwable * @throws \Utopia\Database\Exception @@ -87,7 +91,8 @@ class Certificates extends Action Certificate $queueForCertificates, Log $log, CertificatesAdapter $certificates, - array $plan + array $plan, + ValidatorAuthorization $authorization, ): void { $payload = $message->getPayload() ?? []; @@ -106,11 +111,11 @@ class Certificates extends Action switch ($action) { case Certificate::ACTION_DOMAIN_VERIFICATION: - $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $validationDomain); + $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $authorization, $validationDomain); break; case Certificate::ACTION_GENERATION: - $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $validationDomain); + $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); break; default: @@ -127,10 +132,12 @@ class Certificates extends Action * @param Realtime $queueForRealtime * @param Certificate $queueForCertificates * @param Log $log + * @param ValidatorAuthorization $authorization * @param string|null $validationDomain * @return void - * @throws Throwable * @throws \Utopia\Database\Exception + * @throws NotFound + * @throws \Utopia\Database\Exception\Query */ private function handleDomainVerificationAction( Domain $domain, @@ -141,12 +148,13 @@ class Certificates extends Action Realtime $queueForRealtime, Certificate $queueForCertificates, Log $log, + ValidatorAuthorization $authorization, ?string $validationDomain = null ): void { // Get rule $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ + ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); @@ -195,15 +203,23 @@ class Certificates extends Action * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents + * @param Webhook $queueForWebhooks * @param Func $queueForFunctions * @param Realtime $queueForRealtime + * @param Log $log * @param CertificatesAdapter $certificates + * @param ValidatorAuthorization $authorization * @param bool $skipRenewCheck * @param array $plan * @param string|null $validationDomain * @return void + * @throws Authorization + * @throws Conflict + * @throws NotFound + * @throws Structure * @throws Throwable * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Query */ private function handleCertificateGenerationAction( Domain $domain, @@ -216,6 +232,7 @@ class Certificates extends Action Realtime $queueForRealtime, Log $log, CertificatesAdapter $certificates, + ValidatorAuthorization $authorization, bool $skipRenewCheck = false, array $plan = [], ?string $validationDomain = null @@ -252,8 +269,8 @@ class Certificates extends Action // Get rule document for domain // TODO: (@Meldiron) Remove after 1.7.x migration $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ + ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 0b2f7c75ae..9687f4f4bb 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -19,12 +19,10 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; -use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -203,7 +201,6 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void - * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -1002,14 +999,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); if ($bucket->isEmpty()) { Console::error('Failed to get bucket for deployment screenshots'); return; } foreach ($screenshotIds as $id) { - $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); + $file = $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index fba5154079..a54b982634 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -15,7 +15,6 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; @@ -337,7 +336,6 @@ class Functions extends Action * @param string|null $eventData * @param string|null $executionId * @return void - * @throws Authorization * @throws Structure * @throws \Utopia\Database\Exception * @throws Conflict diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index e1039510f4..6ef2f1899c 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -80,6 +80,7 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,6 +98,7 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, + Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -134,7 +136,13 @@ class Migrations extends Action } try { - $this->processMigration($migration, $queueForRealtime, $queueForMails, $platform); + $this->processMigration( + $migration, + $queueForRealtime, + $queueForMails, + $platform, + $authorization + ); } finally { $this->dbForProject = null; $this->dbForPlatform = null; @@ -145,7 +153,7 @@ class Migrations extends Action $this->plan = []; $this->sourceReport = []; - gc_collect_cycles(); + \gc_collect_cycles(); } } @@ -319,6 +327,7 @@ class Migrations extends Action Realtime $queueForRealtime, Mail $queueForMails, array $platform, + Authorization $authorization, ): void { $project = $this->project; @@ -435,14 +444,14 @@ class Migrations extends Action $destination?->success(); $source?->success(); - // todo: Move to CSV hook + // TODO: Move to CSV hook if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization); } } } finally { - $source?->cleanUp(); - $destination?->cleanUp(); + $source?->cleanup(); + $destination?->cleanup(); $transfer = null; $source = null; @@ -457,11 +466,10 @@ class Migrations extends Action * @param Document $project * @param Document $migration * @param Mail $queueForMails + * @param Realtime $queueForRealtime + * @param array $platform + * @param Authorization $authorization * @return void - * @throws AuthorizationException - * @throws Structure - * @throws \Utopia\Database\Exception - * @throws Exception */ protected function handleCSVExportComplete( Document $project, @@ -469,6 +477,7 @@ class Migrations extends Action Mail $queueForMails, Realtime $queueForRealtime, array $platform, + Authorization $authorization, ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -482,7 +491,7 @@ class Migrations extends Action throw new \Exception('User ' . $userInternalId . ' not found'); } - $bucket = Authorization::skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new \Exception('Bucket not found'); } diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index a85b0a897c..cbd22aaee5 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -7,7 +7,6 @@ use Utopia\Auth\Proofs\Token; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; class User extends Document @@ -36,11 +35,11 @@ class User extends Document * * @return array */ - public function getRoles(): array + public function getRoles($authorization): array { $roles = []; - if (!$this->isPrivileged(Authorization::getRoles()) && !$this->isApp(Authorization::getRoles())) { + if (!$this->isPrivileged($authorization->getRoles()) && !$this->isApp($authorization->getRoles())) { if ($this->getId()) { $roles[] = Role::user($this->getId())->toString(); $roles[] = Role::users()->toString(); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index cb449e6ffa..c87279f126 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -214,7 +214,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isAppUser = User::isApp($roles); if ($isAppUser) { @@ -237,4 +237,11 @@ class Request extends UtopiaRequest ksort($params); return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } + + private ?Authorization $authorization = null; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 56fed746d9..6d47d4d150 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -10,7 +10,7 @@ abstract class Filter private array $params; private ?Database $dbForProject; - public function __construct(Database $dbForProject = null, array $params = []) + public function __construct(?Database $dbForProject = null, array $params = []) { $this->params = $params; $this->dbForProject = $dbForProject; diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 69e7da6b7a..e3d5fe2f79 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -7,7 +7,6 @@ use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; class V20 extends Filter { @@ -138,7 +137,7 @@ class V20 extends Filter } try { - $database = Authorization::skip(fn () => $dbForProject->getDocument( + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'databases', $databaseId )); @@ -150,7 +149,7 @@ class V20 extends Filter } try { - $collection = Authorization::skip(fn () => $dbForProject->getDocument( + $collection = $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId )); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 1dfaa1a41f..f2ac486f82 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -483,7 +483,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isPrivilegedUser = DBUser::isPrivileged($roles); $isAppUser = DBUser::isApp($roles); @@ -651,4 +651,11 @@ class Response extends SwooleResponse self::$showSensitive = false; } } + + private ?Authorization $authorization = null; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index 6496aa285a..0c9854160e 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,19 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + + return $this->authorization; + } + public function createCollection(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ @@ -111,8 +124,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -134,7 +147,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +158,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -222,7 +235,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index 2f69c037d0..84cb4bce3a 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,19 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + + public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ @@ -111,8 +124,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicRows = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -134,7 +147,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +158,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -222,7 +235,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateRow['headers']['status-code']); foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } diff --git a/tests/e2e/Services/Tokens/TokensBase.php b/tests/e2e/Services/Tokens/TokensBase.php index a4461c06c2..ca6feed5fa 100644 --- a/tests/e2e/Services/Tokens/TokensBase.php +++ b/tests/e2e/Services/Tokens/TokensBase.php @@ -94,7 +94,7 @@ trait TokensBase $this->assertEquals(401, $failedPreview['body']['code']); $this->assertEquals(401, $failedPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedPreview['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedPreview['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedPreview['body']['message']); // Extended file preview. Should fail as an anonymous user with no form of any access to the file. $failedCustomPreview = $this->client->call( @@ -113,7 +113,7 @@ trait TokensBase $this->assertEquals(401, $failedCustomPreview['body']['code']); $this->assertEquals(401, $failedCustomPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedCustomPreview['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedCustomPreview['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedCustomPreview['body']['message']); // File view. Should fail as an anonymous user with no form of any access to the file. $failedView = $this->client->call( @@ -124,7 +124,7 @@ trait TokensBase $this->assertEquals(401, $failedView['body']['code']); $this->assertEquals(401, $failedView['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedView['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedView['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedView['body']['message']); // File download. Should fail as an anonymous user with no form of any access to the file. $failedDownload = $this->client->call( @@ -135,7 +135,7 @@ trait TokensBase $this->assertEquals(401, $failedDownload['body']['code']); $this->assertEquals(401, $failedDownload['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedDownload['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedDownload['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedDownload['body']['message']); return $data; } diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 42e433568f..7df5b8d1e6 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -7,6 +7,7 @@ use Appwrite\Utopia\Database\Documents\User; use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -33,6 +34,19 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; + + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + public function setUp(): void { /** @@ -65,7 +79,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -89,7 +103,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); diff --git a/tests/unit/Utopia/Database/Documents/UserTest.php b/tests/unit/Utopia/Database/Documents/UserTest.php index 4675e8d73f..d5706e7bec 100644 --- a/tests/unit/Utopia/Database/Documents/UserTest.php +++ b/tests/unit/Utopia/Database/Documents/UserTest.php @@ -14,13 +14,25 @@ use Utopia\Database\Validator\Roles; class UserTest extends TestCase { + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + /** * Reset Roles */ public function tearDown(): void { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); + $this->getAuthorization()->cleanRoles(); + $this->getAuthorization()->addRole(Role::any()->toString()); } public function testSessionVerify(): void @@ -197,7 +209,7 @@ class UserTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -233,7 +245,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -254,21 +266,21 @@ class UserTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles); // Enable single verification type $user['emailVerification'] = true; - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); } public function testPrivilegedUserRoles(): void { - Authorization::setRole(User::ROLE_OWNER); + $this->getAuthorization()->addRole(User::ROLE_OWNER); $user = new User([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -293,8 +305,7 @@ class UserTest extends TestCase ] ] ]); - - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -312,7 +323,7 @@ class UserTest extends TestCase public function testAppUserRoles(): void { - Authorization::setRole(User::ROLE_APPS); + $this->getAuthorization()->addRole(User::ROLE_APPS); $user = new User([ '$id' => ID::custom('123'), 'memberships' => [ @@ -336,7 +347,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); From e2627d784b07e22e512c1d41bae244a07f0d9691 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 Jan 2026 19:27:51 +1300 Subject: [PATCH 24/52] Fix router param --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 671c948e93..e335f284b7 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1151,7 +1151,7 @@ App::options() $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } From f482e6de68b151fd90d33f5846d105db94815888 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 14:58:22 +0530 Subject: [PATCH 25/52] update: specs generation to exclude mock auth providers. --- .../SDK/Specification/Format/OpenAPI3.php | 63 ++++++++++++++++++- .../SDK/Specification/Format/Swagger2.php | 53 +++++++++++++++- 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 0be3240ed7..0fd82fdd7d 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -12,6 +12,7 @@ use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\Operation; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Any; +use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -906,6 +907,66 @@ class OpenAPI3 extends Format \ksort($output['paths']); - return $output; + return $this->filterOAuthProviders($output); + } + + /** + * Filter OAuth providers from spec. + * + * @param array $spec + * @return array + */ + protected function filterOAuthProviders(array $spec): array + { + if (!isset($spec['paths'])) { + return $spec; + } + + $oAuthProviders = Config::getParam('oAuthProviders', []); + + foreach ($spec['paths'] as &$path) { + foreach ($path as &$method) { + if (isset($method['parameters'])) { + foreach ($method['parameters'] as &$param) { + if (isset($param['name']) && $param['name'] === 'provider') { + if (isset($param['schema']['enum'])) { + $param['schema']['enum'] = $this->filterProviderList($param['schema']['enum'], $oAuthProviders, 'mock'); + } + if (isset($param['schema']['items']['enum'])) { + $param['schema']['items']['enum'] = $this->filterProviderList($param['schema']['items']['enum'], $oAuthProviders, 'mock'); + } + } + } + } + + // Also check requestBody for provider parameter + if (isset($method['requestBody']['content']['application/json']['schema']['properties']['provider']['enum'])) { + $method['requestBody']['content']['application/json']['schema']['properties']['provider']['enum'] = + $this->filterProviderList( + $method['requestBody']['content']['application/json']['schema']['properties']['provider']['enum'], + $oAuthProviders, + 'mock' + ); + } + } + } + + return $spec; + } + + /** + * Filter provider list to remove providers based on a given key + * + * @param array $providers + * @param array $oAuthProviders + * @param string $key + * @return array + */ + protected function filterProviderList( + array $providers, + array $oAuthProviders, + string $key, + ): array { + return array_values(array_filter($providers, fn ($provider) => empty($oAuthProviders[$provider][$key]))); } } diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index fe663c6f55..5e5a7a98ea 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -12,6 +12,7 @@ use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\Operation; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Any; +use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -902,6 +903,56 @@ class Swagger2 extends Format \ksort($output['paths']); - return $output; + return $this->filterOAuthProviders($output); + } + + /** + * Filter OAuth providers from spec. + * + * @param array $spec + * @return array + */ + protected function filterOAuthProviders(array $spec): array + { + if (!isset($spec['paths'])) { + return $spec; + } + + $oAuthProviders = Config::getParam('oAuthProviders', []); + + foreach ($spec['paths'] as &$path) { + foreach ($path as &$method) { + if (isset($method['parameters'])) { + foreach ($method['parameters'] as &$param) { + if (isset($param['name']) && $param['name'] === 'provider') { + if (isset($param['enum'])) { + $param['enum'] = $this->filterProviderList($param['enum'], $oAuthProviders, 'mock'); + } + if (isset($param['items']['enum'])) { + $param['items']['enum'] = $this->filterProviderList($param['items']['enum'], $oAuthProviders, 'mock'); + } + } + } + } + } + } + + return $spec; + } + + /** + * Filter provider list to remove providers based on a given key. + * + * @param array $providers + * @param array $oAuthProviders + * @param string $key + * @return array + */ + protected function filterProviderList( + array $providers, + array $oAuthProviders, + string $key, + ): array { + return array_values(array_filter($providers, fn ($provider) => empty($oAuthProviders[$provider][$key]))); } } From e3ae7daab45b1a2017f64db6498714a03d0158c7 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 14:58:42 +0530 Subject: [PATCH 26/52] regen: specs. --- app/config/specs/open-api3-latest-client.json | 8 ++------ app/config/specs/open-api3-latest-console.json | 12 +++--------- app/config/specs/open-api3-latest-server.json | 4 +--- app/config/specs/swagger2-latest-client.json | 8 ++------ app/config/specs/swagger2-latest-console.json | 8 ++------ app/config/specs/swagger2-latest-server.json | 4 +--- 6 files changed, 11 insertions(+), 33 deletions(-) diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 4bb90a535f..942e83c234 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -2584,9 +2584,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3518,9 +3516,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index a92b8d86e4..f7cbca76a5 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -2594,9 +2594,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3516,9 +3514,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -28254,9 +28250,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index ff308095d6..76e3a2a45c 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -3217,9 +3217,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index ae64cba59b..1d02df124a 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -2694,9 +2694,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3652,9 +3650,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index ea0333f744..f0e1c5608c 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -2720,9 +2720,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3666,9 +3664,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 95188083f6..6ad3eb4bce 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -3357,9 +3357,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], From 91240e0ca7027ae8df057de67d314e37339be2d8 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 15:10:42 +0530 Subject: [PATCH 27/52] update: address comments. regen: specs. --- app/config/specs/swagger2-latest-console.json | 4 +--- .../SDK/Specification/Format/OpenAPI3.php | 16 +++++++++------- .../SDK/Specification/Format/Swagger2.php | 12 ++++++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index f0e1c5608c..17064287be 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -28351,9 +28351,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 0fd82fdd7d..0370e90c9e 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -940,13 +940,15 @@ class OpenAPI3 extends Format } // Also check requestBody for provider parameter - if (isset($method['requestBody']['content']['application/json']['schema']['properties']['provider']['enum'])) { - $method['requestBody']['content']['application/json']['schema']['properties']['provider']['enum'] = - $this->filterProviderList( - $method['requestBody']['content']['application/json']['schema']['properties']['provider']['enum'], - $oAuthProviders, - 'mock' - ); + if (isset($method['requestBody']['content']['application/json']['schema']['properties']['provider'])) { + $providerProp = &$method['requestBody']['content']['application/json']['schema']['properties']['provider']; + if (isset($providerProp['enum'])) { + $providerProp['enum'] = $this->filterProviderList($providerProp['enum'], $oAuthProviders, 'mock'); + } + + if (isset($providerProp['items']['enum'])) { + $providerProp['items']['enum'] = $this->filterProviderList($providerProp['items']['enum'], $oAuthProviders, 'mock'); + } } } } diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 5e5a7a98ea..1d5d4b754e 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -932,6 +932,18 @@ class Swagger2 extends Format $param['items']['enum'] = $this->filterProviderList($param['items']['enum'], $oAuthProviders, 'mock'); } } + + if (isset($param['schema']['properties']['provider'])) { + if (isset($param['schema']['properties']['provider']['enum'])) { + $param['schema']['properties']['provider']['enum'] = + $this->filterProviderList($param['schema']['properties']['provider']['enum'], $oAuthProviders, 'mock'); + } + + if (isset($param['schema']['properties']['provider']['items']['enum'])) { + $param['schema']['properties']['provider']['items']['enum'] = + $this->filterProviderList($param['schema']['properties']['provider']['items']['enum'], $oAuthProviders, 'mock'); + } + } } } } From 0ec515779ebaa46389e2294686cba5bd9dfc09ab Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 15:29:30 +0530 Subject: [PATCH 28/52] update: address comments. regen: specs. --- app/config/specs/open-api3-latest-client.json | 8 +- .../specs/open-api3-latest-console.json | 12 ++- app/config/specs/open-api3-latest-server.json | 4 +- app/config/specs/swagger2-latest-client.json | 8 +- app/config/specs/swagger2-latest-console.json | 12 ++- app/config/specs/swagger2-latest-server.json | 4 +- .../SDK/Specification/Format/OpenAPI3.php | 99 ++++++----------- .../SDK/Specification/Format/Swagger2.php | 101 ++++++------------ 8 files changed, 98 insertions(+), 150 deletions(-) diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 942e83c234..4bb90a535f 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -2584,7 +2584,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3516,7 +3518,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index f7cbca76a5..a92b8d86e4 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -2594,7 +2594,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3514,7 +3516,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -28250,7 +28254,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 76e3a2a45c..ff308095d6 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -3217,7 +3217,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 1d02df124a..ae64cba59b 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -2694,7 +2694,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3650,7 +3652,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 17064287be..ea0333f744 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -2720,7 +2720,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3664,7 +3666,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -28351,7 +28355,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 6ad3eb4bce..95188083f6 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -3357,7 +3357,9 @@ "yammer", "yandex", "zoho", - "zoom" + "zoom", + "mock", + "mock-unverified" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 0370e90c9e..782ed217e5 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -12,7 +12,6 @@ use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\Operation; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Any; -use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -585,18 +584,31 @@ class OpenAPI3 extends Format // Iterate from the blackList. If it matches with the current one, then it is a blackList // Do not add the enum $allowed = true; + $excludeKeys = null; foreach ($this->enumBlacklist as $blacklist) { if ( $blacklist['namespace'] == $sdk->getNamespace() && $blacklist['method'] == $methodName && $blacklist['parameter'] == $name ) { - $allowed = false; + // 'exclude' => true means full exclude + if (isset($blacklist['exclude']) && $blacklist['exclude'] === true) { + $allowed = false; + break; + } + + if (isset($blacklist['excludeKeys'])) { + $excludeKeys = $blacklist['excludeKeys']; + } break; } } if ($allowed && $validator->getType() === 'string') { - $node['schema']['items']['enum'] = \array_values($validator->getList()); + $enumValues = \array_values($validator->getList()); + if ($excludeKeys !== null) { + $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + } + $node['schema']['items']['enum'] = $enumValues; $node['schema']['items']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); $node['schema']['items']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); } @@ -610,18 +622,31 @@ class OpenAPI3 extends Format // Iterate from the blackList. If it matches with the current one, then it is a blackList // Do not add the enum $allowed = true; + $excludeKeys = null; foreach ($this->enumBlacklist as $blacklist) { if ( $blacklist['namespace'] == $sdk->getNamespace() && $blacklist['method'] == $methodName && $blacklist['parameter'] == $name ) { - $allowed = false; + // 'exclude' => true means full exclude + if (isset($blacklist['exclude']) && $blacklist['exclude'] === true) { + $allowed = false; + break; + } + + if (isset($blacklist['excludeKeys'])) { + $excludeKeys = $blacklist['excludeKeys']; + } break; } } if ($allowed && $validator->getType() === 'string') { - $node['schema']['enum'] = \array_values($validator->getList()); + $enumValues = \array_values($validator->getList()); + if ($excludeKeys !== null) { + $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + } + $node['schema']['enum'] = $enumValues; $node['schema']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); $node['schema']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); } @@ -907,68 +932,6 @@ class OpenAPI3 extends Format \ksort($output['paths']); - return $this->filterOAuthProviders($output); - } - - /** - * Filter OAuth providers from spec. - * - * @param array $spec - * @return array - */ - protected function filterOAuthProviders(array $spec): array - { - if (!isset($spec['paths'])) { - return $spec; - } - - $oAuthProviders = Config::getParam('oAuthProviders', []); - - foreach ($spec['paths'] as &$path) { - foreach ($path as &$method) { - if (isset($method['parameters'])) { - foreach ($method['parameters'] as &$param) { - if (isset($param['name']) && $param['name'] === 'provider') { - if (isset($param['schema']['enum'])) { - $param['schema']['enum'] = $this->filterProviderList($param['schema']['enum'], $oAuthProviders, 'mock'); - } - if (isset($param['schema']['items']['enum'])) { - $param['schema']['items']['enum'] = $this->filterProviderList($param['schema']['items']['enum'], $oAuthProviders, 'mock'); - } - } - } - } - - // Also check requestBody for provider parameter - if (isset($method['requestBody']['content']['application/json']['schema']['properties']['provider'])) { - $providerProp = &$method['requestBody']['content']['application/json']['schema']['properties']['provider']; - if (isset($providerProp['enum'])) { - $providerProp['enum'] = $this->filterProviderList($providerProp['enum'], $oAuthProviders, 'mock'); - } - - if (isset($providerProp['items']['enum'])) { - $providerProp['items']['enum'] = $this->filterProviderList($providerProp['items']['enum'], $oAuthProviders, 'mock'); - } - } - } - } - - return $spec; - } - - /** - * Filter provider list to remove providers based on a given key - * - * @param array $providers - * @param array $oAuthProviders - * @param string $key - * @return array - */ - protected function filterProviderList( - array $providers, - array $oAuthProviders, - string $key, - ): array { - return array_values(array_filter($providers, fn ($provider) => empty($oAuthProviders[$provider][$key]))); + return $output; } } diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 1d5d4b754e..97d12f5192 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -12,7 +12,6 @@ use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\Operation; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Any; -use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -572,16 +571,28 @@ class Swagger2 extends Format $node['x-example'] = $param['example']; } - // Iterate the blackList. If it matches with the current one, then it is blackListed $allowed = true; + $excludeKeys = null; foreach ($this->enumBlacklist as $blacklist) { if ($blacklist['namespace'] == $namespace && $blacklist['method'] == $methodName && $blacklist['parameter'] == $name) { - $allowed = false; + // 'exclude' => true means full exclude + if (isset($blacklist['exclude']) && $blacklist['exclude'] === true) { + $allowed = false; + break; + } + + if (isset($blacklist['excludeKeys'])) { + $excludeKeys = $blacklist['excludeKeys']; + } break; } } if ($allowed && $validator->getType() === 'string') { - $node['items']['enum'] = \array_values($validator->getList()); + $enumValues = \array_values($validator->getList()); + if ($excludeKeys !== null) { + $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + } + $node['items']['enum'] = $enumValues; $node['items']['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); $node['items']['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); } @@ -592,16 +603,28 @@ class Swagger2 extends Format $node['type'] = $validator->getType(); $node['x-example'] = ($param['example'] ?? '') ?: $validator->getList()[0]; - // Iterate the blackList. If it matches with the current one, then it is blackListed $allowed = true; + $excludeKeys = null; foreach ($this->enumBlacklist as $blacklist) { if ($blacklist['namespace'] == $namespace && $blacklist['method'] == $methodName && $blacklist['parameter'] == $name) { - $allowed = false; + // 'exclude' => true means full exclude + if (isset($blacklist['exclude']) && $blacklist['exclude'] === true) { + $allowed = false; + break; + } + + if (isset($blacklist['excludeKeys'])) { + $excludeKeys = $blacklist['excludeKeys']; + } break; } } if ($allowed && $validator->getType() === 'string') { - $node['enum'] = \array_values($validator->getList()); + $enumValues = \array_values($validator->getList()); + if ($excludeKeys !== null) { + $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + } + $node['enum'] = $enumValues; $node['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); $node['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); } @@ -903,68 +926,6 @@ class Swagger2 extends Format \ksort($output['paths']); - return $this->filterOAuthProviders($output); - } - - /** - * Filter OAuth providers from spec. - * - * @param array $spec - * @return array - */ - protected function filterOAuthProviders(array $spec): array - { - if (!isset($spec['paths'])) { - return $spec; - } - - $oAuthProviders = Config::getParam('oAuthProviders', []); - - foreach ($spec['paths'] as &$path) { - foreach ($path as &$method) { - if (isset($method['parameters'])) { - foreach ($method['parameters'] as &$param) { - if (isset($param['name']) && $param['name'] === 'provider') { - if (isset($param['enum'])) { - $param['enum'] = $this->filterProviderList($param['enum'], $oAuthProviders, 'mock'); - } - if (isset($param['items']['enum'])) { - $param['items']['enum'] = $this->filterProviderList($param['items']['enum'], $oAuthProviders, 'mock'); - } - } - - if (isset($param['schema']['properties']['provider'])) { - if (isset($param['schema']['properties']['provider']['enum'])) { - $param['schema']['properties']['provider']['enum'] = - $this->filterProviderList($param['schema']['properties']['provider']['enum'], $oAuthProviders, 'mock'); - } - - if (isset($param['schema']['properties']['provider']['items']['enum'])) { - $param['schema']['properties']['provider']['items']['enum'] = - $this->filterProviderList($param['schema']['properties']['provider']['items']['enum'], $oAuthProviders, 'mock'); - } - } - } - } - } - } - - return $spec; - } - - /** - * Filter provider list to remove providers based on a given key. - * - * @param array $providers - * @param array $oAuthProviders - * @param string $key - * @return array - */ - protected function filterProviderList( - array $providers, - array $oAuthProviders, - string $key, - ): array { - return array_values(array_filter($providers, fn ($provider) => empty($oAuthProviders[$provider][$key]))); + return $output; } } From 6c866be9f3befd363d5babed726e1a03176f1b45 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 14 Jan 2026 15:57:21 +0530 Subject: [PATCH 29/52] Fix execution status not updating if usage stats trigger fails Move the execution document update inside the finally block and wrap it in try-catch to ensure the execution record is always updated, even if queueForStatsUsage->trigger() throws an exception. --- src/Appwrite/Platform/Workers/Functions.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index a54b982634..d047d0925e 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -462,7 +462,11 @@ class Functions extends Action if ($execution->getAttribute('status') !== 'processing') { $execution->setAttribute('status', 'processing'); - $execution = $dbForProject->updateDocument('executions', $executionId, $execution); + try { + $execution = $dbForProject->updateDocument('executions', $executionId, $execution); + } catch (\Throwable $e) { + $log->addExtra('updateError', $e->getMessage()); + } } $durationStart = \microtime(true); @@ -605,6 +609,13 @@ class Functions extends Action $error = $th->getMessage(); $errorCode = $th->getCode(); } finally { + /** Update execution status */ + try { + $execution = $dbForProject->updateDocument('executions', $executionId, $execution); + } catch (\Throwable $e) { + $log->addExtra('updateError', $e->getMessage()); + } + /** Trigger usage queue */ $queueForStatsUsage ->setProject($project) @@ -621,8 +632,6 @@ class Functions extends Action ; } - $execution = $dbForProject->updateDocument('executions', $executionId, $execution); - $executionModel = new Execution(); $realtimeExecution = $executionModel->filter(new Document($execution->getArrayCopy())); $realtimeExecution = $realtimeExecution->getArrayCopy(\array_keys($executionModel->getRules())); From d6d8729983e916c728549f0e26103171a1b270cd Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 16:36:44 +0530 Subject: [PATCH 30/52] bump: sdk generator. --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 20b5c754eb..d52a16365c 100644 --- a/composer.lock +++ b/composer.lock @@ -5481,16 +5481,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.8.11", + "version": "1.8.14", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "936404bbcbf4cd692bac102f2912b6c97ac87215" + "reference": "a43e8ba5d539e48f0717df284dbd5dc1fb659d6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/936404bbcbf4cd692bac102f2912b6c97ac87215", - "reference": "936404bbcbf4cd692bac102f2912b6c97ac87215", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a43e8ba5d539e48f0717df284dbd5dc1fb659d6b", + "reference": "a43e8ba5d539e48f0717df284dbd5dc1fb659d6b", "shasum": "" }, "require": { @@ -5526,9 +5526,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.8.11" + "source": "https://github.com/appwrite/sdk-generator/tree/1.8.14" }, - "time": "2026-01-12T08:41:56+00:00" + "time": "2026-01-14T10:42:32+00:00" }, { "name": "doctrine/annotations", From 6cd19bf330c9cbc93a0fa29a2bb9ce90241d1f4a Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 16:42:30 +0530 Subject: [PATCH 31/52] address comment for key values on enums. --- src/Appwrite/SDK/Specification/Format/OpenAPI3.php | 12 ++++++++++-- src/Appwrite/SDK/Specification/Format/Swagger2.php | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 782ed217e5..ed5beff853 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -610,7 +610,11 @@ class OpenAPI3 extends Format } $node['schema']['items']['enum'] = $enumValues; $node['schema']['items']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); - $node['schema']['items']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); + $enumKeys = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); + if ($excludeKeys !== null) { + $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); + } + $node['schema']['items']['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { $node['schema']['items']['format'] = $validator->getFormat() ?? 'int32'; @@ -648,7 +652,11 @@ class OpenAPI3 extends Format } $node['schema']['enum'] = $enumValues; $node['schema']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); - $node['schema']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); + $enumKeys = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); + if ($excludeKeys !== null) { + $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); + } + $node['schema']['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { $node['schema']['format'] = $validator->getFormat() ?? 'int32'; diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 97d12f5192..dc135f15d4 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -594,7 +594,11 @@ class Swagger2 extends Format } $node['items']['enum'] = $enumValues; $node['items']['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); - $node['items']['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); + $enumKeys = $this->getRequestEnumKeys($namespace, $methodName, $name); + if ($excludeKeys !== null) { + $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); + } + $node['items']['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { $node['items']['format'] = $validator->getFormat() ?? 'int32'; @@ -626,7 +630,11 @@ class Swagger2 extends Format } $node['enum'] = $enumValues; $node['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); - $node['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); + $enumKeys = $this->getRequestEnumKeys($namespace, $methodName, $name); + if ($excludeKeys !== null) { + $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); + } + $node['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { $node['format'] = $validator->getFormat() ?? 'int32'; From 08cd610823b7a4f049ff309badea6555fff3752f Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 16:47:21 +0530 Subject: [PATCH 32/52] exclude the mocks. --- app/config/specs/open-api3-latest-client.json | 8 ++------ app/config/specs/open-api3-latest-console.json | 8 ++------ app/config/specs/open-api3-latest-server.json | 4 +--- app/config/specs/swagger2-latest-client.json | 8 ++------ app/config/specs/swagger2-latest-console.json | 8 ++------ app/config/specs/swagger2-latest-server.json | 4 +--- src/Appwrite/SDK/Specification/Format.php | 18 ++++++++++++++++++ 7 files changed, 28 insertions(+), 30 deletions(-) diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 4bb90a535f..942e83c234 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -2584,9 +2584,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3518,9 +3516,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index a92b8d86e4..97c032720a 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -2594,9 +2594,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3516,9 +3514,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index ff308095d6..76e3a2a45c 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -3217,9 +3217,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index ae64cba59b..1d02df124a 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -2694,9 +2694,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3652,9 +3650,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index ea0333f744..f0e1c5608c 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -2720,9 +2720,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3666,9 +3664,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 95188083f6..6ad3eb4bce 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -3357,9 +3357,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/src/Appwrite/SDK/Specification/Format.php b/src/Appwrite/SDK/Specification/Format.php index 3d2ebad556..53f96d490e 100644 --- a/src/Appwrite/SDK/Specification/Format.php +++ b/src/Appwrite/SDK/Specification/Format.php @@ -48,6 +48,24 @@ abstract class Format 'namespace' => 'users', 'method' => 'getUsage', 'parameter' => 'provider' + ], + [ + 'namespace' => 'account', + 'method' => 'createOAuth2Session', + 'parameter' => 'provider', + 'excludeKeys' => ['mock', 'mock-unverified'] + ], + [ + 'namespace' => 'account', + 'method' => 'createOAuth2Token', + 'parameter' => 'provider', + 'excludeKeys' => ['mock', 'mock-unverified'] + ], + [ + 'namespace' => 'account', + 'method' => 'updateMagicURLSession', + 'parameter' => 'provider', + 'excludeKeys' => ['mock', 'mock-unverified'] ] ]; From 479a583ff593c99553de7bc5c2686fd5110144a9 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 16:55:47 +0530 Subject: [PATCH 33/52] exclude the mocks. --- app/config/specs/open-api3-1.8.x-client.json | 8 ++------ app/config/specs/open-api3-1.8.x-console.json | 12 ++++-------- app/config/specs/open-api3-1.8.x-server.json | 8 +++----- app/config/specs/swagger2-1.8.x-client.json | 8 ++------ app/config/specs/swagger2-1.8.x-console.json | 12 ++++-------- app/config/specs/swagger2-1.8.x-server.json | 8 +++----- 6 files changed, 18 insertions(+), 38 deletions(-) diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json index 4bb90a535f..942e83c234 100644 --- a/app/config/specs/open-api3-1.8.x-client.json +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -2584,9 +2584,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3518,9 +3516,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index 22f247843f..97c032720a 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -2594,9 +2594,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -3516,9 +3514,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -61445,7 +61441,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -61491,7 +61487,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json index e82f3e5b78..76e3a2a45c 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -3217,9 +3217,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] @@ -45416,7 +45414,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -45462,7 +45460,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json index ae64cba59b..1d02df124a 100644 --- a/app/config/specs/swagger2-1.8.x-client.json +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -2694,9 +2694,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3652,9 +3650,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index 7672fc09d4..f0e1c5608c 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -2720,9 +2720,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -3666,9 +3664,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -61384,7 +61380,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -61430,7 +61426,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index 284c917919..6ad3eb4bce 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -3357,9 +3357,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [], @@ -45349,7 +45347,7 @@ "status": { "type": "string", "description": "Status of delivery.", - "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed.", + "x-example": "processing", "enum": [ "draft", "processing", @@ -45395,7 +45393,7 @@ "subject": "Welcome to Appwrite", "content": "Hi there, welcome to Appwrite family." }, - "status": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + "status": "processing" } }, "topic": { From 4d2f63139335aa11e750c4e2cc7f8c00550cc007 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 17:07:33 +0530 Subject: [PATCH 34/52] update: exclude the mocks. update: nice group based blacklisting. --- .../specs/open-api3-latest-console.json | 4 +- app/config/specs/swagger2-latest-console.json | 4 +- src/Appwrite/SDK/Specification/Format.php | 100 ++++++++++++++---- 3 files changed, 79 insertions(+), 29 deletions(-) diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 97c032720a..f7cbca76a5 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -28250,9 +28250,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index f0e1c5608c..17064287be 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -28351,9 +28351,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/src/Appwrite/SDK/Specification/Format.php b/src/Appwrite/SDK/Specification/Format.php index 53f96d490e..ed77e568f4 100644 --- a/src/Appwrite/SDK/Specification/Format.php +++ b/src/Appwrite/SDK/Specification/Format.php @@ -40,35 +40,46 @@ abstract class Format 'license.url' => '', ]; - /* - * Blacklist to omit the enum types for the given route's parameter - */ - protected array $enumBlacklist = [ + private const array OAUTH_PROVIDER_BLACKLIST = [ + [ + 'namespace' => 'account', + 'methods' => [ + 'createOAuth2Session', + 'createOAuth2Token', + 'updateMagicURLSession' + ], + 'parameter' => 'provider', + 'excludeKeys' => [ + 'mock', + 'mock-unverified' + ], + ], + [ + 'namespace' => 'projects', + 'methods' => [ + 'updateOAuth2' + ], + 'parameter' => 'provider', + 'excludeKeys' => [ + 'mock', + 'mock-unverified' + ], + ], + ]; + + private const array PROVIDER_USAGE_BLACKLIST = [ [ 'namespace' => 'users', - 'method' => 'getUsage', - 'parameter' => 'provider' - ], - [ - 'namespace' => 'account', - 'method' => 'createOAuth2Session', + 'methods' => [ + 'getUsage' + ], 'parameter' => 'provider', - 'excludeKeys' => ['mock', 'mock-unverified'] + 'exclude' => true, /* fully excluded */ ], - [ - 'namespace' => 'account', - 'method' => 'createOAuth2Token', - 'parameter' => 'provider', - 'excludeKeys' => ['mock', 'mock-unverified'] - ], - [ - 'namespace' => 'account', - 'method' => 'updateMagicURLSession', - 'parameter' => 'provider', - 'excludeKeys' => ['mock', 'mock-unverified'] - ] ]; + protected array $enumBlacklist = []; + public function __construct(App $app, array $services, array $routes, array $models, array $keys, int $authCount, string $platform) { $this->app = $app; @@ -78,6 +89,49 @@ abstract class Format $this->keys = $keys; $this->authCount = $authCount; $this->platform = $platform; + + $this->enumBlacklist = $this->buildEnumBlacklist(); + } + + protected function buildEnumBlacklist(): array + { + $blacklist = []; + + foreach (self::OAUTH_PROVIDER_BLACKLIST as $config) { + foreach ($config['methods'] as $method) { + $entry = [ + 'namespace' => $config['namespace'], + 'method' => $method, + 'parameter' => $config['parameter'], + ]; + if (isset($config['excludeKeys'])) { + $entry['excludeKeys'] = $config['excludeKeys']; + } + if (isset($config['exclude'])) { + $entry['exclude'] = $config['exclude']; + } + $blacklist[] = $entry; + } + } + + foreach (self::PROVIDER_USAGE_BLACKLIST as $config) { + foreach ($config['methods'] as $method) { + $entry = [ + 'namespace' => $config['namespace'], + 'method' => $method, + 'parameter' => $config['parameter'], + ]; + if (isset($config['excludeKeys'])) { + $entry['excludeKeys'] = $config['excludeKeys']; + } + if (isset($config['exclude'])) { + $entry['exclude'] = $config['exclude']; + } + $blacklist[] = $entry; + } + } + + return $blacklist; } /** From bc6ecbd22cd34b1063332561587890e9bfb0f25d Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 14 Jan 2026 17:15:33 +0530 Subject: [PATCH 35/52] address comments. --- app/config/specs/open-api3-1.8.x-console.json | 4 +- app/config/specs/swagger2-1.8.x-console.json | 4 +- .../SDK/Specification/Format/OpenAPI3.php | 40 +++++++++++++------ .../SDK/Specification/Format/Swagger2.php | 40 +++++++++++++------ 4 files changed, 58 insertions(+), 30 deletions(-) diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index 97c032720a..f7cbca76a5 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -28250,9 +28250,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index f0e1c5608c..17064287be 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -28351,9 +28351,7 @@ "yammer", "yandex", "zoho", - "zoom", - "mock", - "mock-unverified" + "zoom" ], "x-enum-name": "OAuthProvider", "x-enum-keys": [] diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index ed5beff853..27dcf92923 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -604,16 +604,24 @@ class OpenAPI3 extends Format } } if ($allowed && $validator->getType() === 'string') { - $enumValues = \array_values($validator->getList()); + $allValues = \array_values($validator->getList()); + $allKeys = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); + if ($excludeKeys !== null) { - $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + $keepIndices = []; + foreach ($allValues as $index => $value) { + if (!\in_array($value, $excludeKeys, true)) { + $keepIndices[] = $index; + } + } + $enumKeys = \array_values(\array_intersect_key($allKeys, \array_flip($keepIndices))); + $enumValues = \array_values(\array_intersect_key($allValues, \array_flip($keepIndices))); + } else { + $enumKeys = $allKeys; + $enumValues = $allValues; } $node['schema']['items']['enum'] = $enumValues; $node['schema']['items']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); - $enumKeys = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); - if ($excludeKeys !== null) { - $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); - } $node['schema']['items']['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { @@ -646,16 +654,24 @@ class OpenAPI3 extends Format } } if ($allowed && $validator->getType() === 'string') { - $enumValues = \array_values($validator->getList()); + $allValues = \array_values($validator->getList()); + $allKeys = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); + if ($excludeKeys !== null) { - $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + $keepIndices = []; + foreach ($allValues as $index => $value) { + if (!\in_array($value, $excludeKeys, true)) { + $keepIndices[] = $index; + } + } + $enumKeys = \array_values(\array_intersect_key($allKeys, \array_flip($keepIndices))); + $enumValues = \array_values(\array_intersect_key($allValues, \array_flip($keepIndices))); + } else { + $enumKeys = $allKeys; + $enumValues = $allValues; } $node['schema']['enum'] = $enumValues; $node['schema']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); - $enumKeys = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); - if ($excludeKeys !== null) { - $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); - } $node['schema']['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index dc135f15d4..de25a57ccc 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -588,16 +588,24 @@ class Swagger2 extends Format } } if ($allowed && $validator->getType() === 'string') { - $enumValues = \array_values($validator->getList()); + $allValues = \array_values($validator->getList()); + $allKeys = $this->getRequestEnumKeys($namespace, $methodName, $name); + if ($excludeKeys !== null) { - $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + $keepIndices = []; + foreach ($allValues as $index => $value) { + if (!\in_array($value, $excludeKeys, true)) { + $keepIndices[] = $index; + } + } + $enumKeys = \array_values(\array_intersect_key($allKeys, \array_flip($keepIndices))); + $enumValues = \array_values(\array_intersect_key($allValues, \array_flip($keepIndices))); + } else { + $enumKeys = $allKeys; + $enumValues = $allValues; } $node['items']['enum'] = $enumValues; $node['items']['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); - $enumKeys = $this->getRequestEnumKeys($namespace, $methodName, $name); - if ($excludeKeys !== null) { - $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); - } $node['items']['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { @@ -624,16 +632,24 @@ class Swagger2 extends Format } } if ($allowed && $validator->getType() === 'string') { - $enumValues = \array_values($validator->getList()); + $allValues = \array_values($validator->getList()); + $allKeys = $this->getRequestEnumKeys($namespace, $methodName, $name); + if ($excludeKeys !== null) { - $enumValues = \array_values(\array_filter($enumValues, fn ($key) => !\in_array($key, $excludeKeys, true))); + $keepIndices = []; + foreach ($allValues as $index => $value) { + if (!\in_array($value, $excludeKeys, true)) { + $keepIndices[] = $index; + } + } + $enumKeys = \array_values(\array_intersect_key($allKeys, \array_flip($keepIndices))); + $enumValues = \array_values(\array_intersect_key($allValues, \array_flip($keepIndices))); + } else { + $enumKeys = $allKeys; + $enumValues = $allValues; } $node['enum'] = $enumValues; $node['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); - $enumKeys = $this->getRequestEnumKeys($namespace, $methodName, $name); - if ($excludeKeys !== null) { - $enumKeys = \array_values(\array_filter($enumKeys, fn ($key) => \in_array($key, $enumValues, true))); - } $node['x-enum-keys'] = $enumKeys; } if ($validator->getType() === 'integer') { From e4abc0e0dad7ca118d166c8a786c8cc8ffb76be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 14 Jan 2026 13:16:50 +0100 Subject: [PATCH 36/52] Add more file params (encryption, compression) --- src/Appwrite/Utopia/Response/Model/File.php | 24 ++++ .../Storage/StorageCustomClientTest.php | 113 ++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/src/Appwrite/Utopia/Response/Model/File.php b/src/Appwrite/Utopia/Response/Model/File.php index 11a128abcc..c4e36286ea 100644 --- a/src/Appwrite/Utopia/Response/Model/File.php +++ b/src/Appwrite/Utopia/Response/Model/File.php @@ -4,6 +4,8 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use Utopia\Database\Document; +use Utopia\Storage\Compression\Compression; class File extends Model { @@ -77,6 +79,18 @@ class File extends Model 'default' => 0, 'example' => 17890, ]) + ->addRule('encryption', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Whether file contents are encrypted at rest.', + 'default' => false, + 'example' => true, + ]) + ->addRule('compression', [ + 'type' => self::TYPE_STRING, + 'description' => 'Compression algorithm used for the file. Will be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd).', + 'default' => '', + 'example' => 'gzip' + ]) ; } @@ -99,4 +113,14 @@ class File extends Model { return Response::MODEL_FILE; } + + public function filter(Document $document): Document + { + $document->setAttribute('compression', $document->getAttribute('algorithm', '')); + + $encryption = !empty($document->getAttribute('openSSLCipher', '')); + $document->setAttribute('encryption', $encryption); + + return $document; + } } diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index ec9f0d0cc7..4d1a0f44c8 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -1447,4 +1447,117 @@ class StorageCustomClientTest extends Scope ]); $this->assertEquals(204, $response['headers']['status-code']); } + + public function testFileEncryptionAndCompression(): void + { + // Create bucket + $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'], + ], [ + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket', + 'permissions' => [ + Permission::read(Role::any()) + ], + 'encryption' => true, + 'compression' => 'gzip' + ]); + $this->assertSame(201, $bucket['headers']['status-code']); + + // Create file + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket['body']['$id'] . '/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', 'transformations.png'), + ]); + $this->assertSame(201, $file['headers']['status-code']); + $this->assertSame('gzip', $file['body']['compression']); + $this->assertSame(true, $file['body']['encryption']); + + // Get file + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'], [ + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertSame(200, $file['headers']['status-code']); + $this->assertSame('gzip', $file['body']['compression']); + $this->assertSame(true, $file['body']['encryption']); + + // List files + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files', [ + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertSame(200, $files['headers']['status-code']); + $this->assertSame(1, $files['body']['total']); + $this->assertSame('gzip', $files['body']['files'][0]['compression']); + $this->assertSame(true, $files['body']['files'][0]['encryption']); + + // Update the bucket + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucket['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'name' => 'Test Bucket', + 'encryption' => false, + 'compression' => 'none' + ]); + + // Existing fie did not update + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'], [ + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertSame(200, $file['headers']['status-code']); + $this->assertSame('gzip', $file['body']['compression']); + $this->assertSame(true, $file['body']['encryption']); + + // Create 2nd file + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket['body']['$id'] . '/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', 'transformations.png'), + ]); + $this->assertSame(201, $file['headers']['status-code']); + $this->assertSame('none', $file['body']['compression']); + $this->assertSame(false, $file['body']['encryption']); + + // Get file + $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'], [ + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertSame(200, $file['headers']['status-code']); + $this->assertSame('none', $file['body']['compression']); + $this->assertSame(false, $file['body']['encryption']); + + // List files + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files', [ + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + $this->assertSame(200, $files['headers']['status-code']); + $this->assertSame(2, $files['body']['total']); + $this->assertSame('none', $files['body']['files'][1]['compression']); + $this->assertSame(false, $files['body']['files'][1]['encryption']); + $this->assertSame('gzip', $files['body']['files'][0]['compression']); + $this->assertSame(true, $files['body']['files'][0]['encryption']); + + // Delete the bucket + $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$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 7b10fe13714f7ba9a2acc06115e4b73985deb2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 14 Jan 2026 14:17:12 +0100 Subject: [PATCH 37/52] typo fix --- tests/e2e/Services/Storage/StorageCustomClientTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index 4d1a0f44c8..0337856779 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -1509,7 +1509,7 @@ class StorageCustomClientTest extends Scope 'compression' => 'none' ]); - // Existing fie did not update + // Existing file did not update $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'], [ 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], From 223bb7f08adeaa9f0b64deac3ff85ece1fc61d7f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 03:07:26 +1300 Subject: [PATCH 38/52] Update lock --- composer.json | 2 +- composer.lock | 46 +++++++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/composer.json b/composer.json index ef833cfb38..f5bab03697 100644 --- a/composer.json +++ b/composer.json @@ -72,7 +72,7 @@ "utopia-php/queue": "0.15.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", - "utopia-php/swoole": "0.8.*", + "utopia-php/swoole": "1.*", "utopia-php/system": "0.9.*", "utopia-php/telemetry": "0.1.*", "utopia-php/vcs": "0.13.*", diff --git a/composer.lock b/composer.lock index d52a16365c..6fead373dd 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": "2d32f0fe31dc03c1f96a2582093afca1", + "content-hash": "33da844fdf5648d1d1a027dfb6ae42bc", "packages": [ { "name": "adhocore/jwt", @@ -3552,16 +3552,16 @@ }, { "name": "utopia-php/audit", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131" + "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/662244bd170bab3ba45fd4470ac2e5a36c980131", - "reference": "662244bd170bab3ba45fd4470ac2e5a36c980131", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/1301ab2607667b9f86456f86895f3e26f8c0c9a7", + "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7", "shasum": "" }, "require": { @@ -3595,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.3" + "source": "https://github.com/utopia-php/audit/tree/2.0.4" }, - "time": "2026-01-13T09:49:40+00:00" + "time": "2026-01-14T07:22:46+00:00" }, { "name": "utopia-php/auth", @@ -3898,16 +3898,16 @@ }, { "name": "utopia-php/database", - "version": "4.4.0", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "783193d5cdc723b3784e8fb399068b17d4228d53" + "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/783193d5cdc723b3784e8fb399068b17d4228d53", - "reference": "783193d5cdc723b3784e8fb399068b17d4228d53", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", + "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", "shasum": "" }, "require": { @@ -3950,9 +3950,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.4.0" + "source": "https://github.com/utopia-php/database/tree/4.5.1" }, - "time": "2026-01-08T04:54:39+00:00" + "time": "2026-01-14T12:07:24+00:00" }, { "name": "utopia-php/detector", @@ -5056,22 +5056,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.4", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" + "reference": "95a937acb393dbf95cccba239d55886e2848ab0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/95a937acb393dbf95cccba239d55886e2848ab0b", + "reference": "95a937acb393dbf95cccba239d55886e2848ab0b", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.*" + "utopia-php/framework": "0.33.37" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5101,9 +5101,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.4" + "source": "https://github.com/utopia-php/swoole/tree/1.0.0" }, - "time": "2025-09-07T09:39:46+00:00" + "time": "2026-01-14T14:00:11+00:00" }, { "name": "utopia-php/system", @@ -5481,7 +5481,7 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.8.14", + "version": "1.8.15", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", @@ -5526,7 +5526,7 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.8.14" + "source": "https://github.com/appwrite/sdk-generator/tree/1.8.15" }, "time": "2026-01-14T10:42:32+00:00" }, @@ -9011,5 +9011,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } From 38687bc24e63b5fcbeec6118521c43a863753769 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 03:48:42 +1300 Subject: [PATCH 39/52] Revert "Merge pull request #11130 from appwrite/feat-auth-instance" This reverts commit c12cad80bbc1f0d44e8c502c648933cfc4c9d263, reversing changes made to 2a17429226220cdce99892f2a938744a47df3d14. # Conflicts: # composer.lock --- app/cli.php | 28 +-- app/config/storage/resource_limits.php | 4 +- app/controllers/api/account.php | 146 ++++++-------- app/controllers/api/graphql.php | 5 +- app/controllers/api/health.php | 18 +- app/controllers/api/messaging.php | 65 +++--- app/controllers/api/migrations.php | 14 +- app/controllers/api/project.php | 9 +- app/controllers/api/teams.php | 63 +++--- app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 60 +++--- app/controllers/general.php | 189 +++++++++--------- app/controllers/shared/api.php | 53 +++-- app/controllers/shared/api/auth.php | 7 +- app/http.php | 28 +-- app/init/database/filters.php | 47 ++--- app/init/resources.php | 106 +++++----- app/realtime.php | 41 +--- app/worker.php | 53 ++--- composer.json | 10 +- composer.lock | 105 +++++----- src/Appwrite/Databases/TransactionState.php | 10 +- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Avatars/Http/Action.php | 10 +- .../Modules/Avatars/Http/Browsers/Get.php | 2 +- .../Avatars/Http/Cards/Cloud/Back/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/Front/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/OG/Get.php | 7 +- .../Modules/Avatars/Http/CreditCards/Get.php | 2 +- .../Modules/Avatars/Http/Flags/Get.php | 2 +- .../Platform/Modules/Compute/Base.php | 41 +--- .../Modules/Console/Http/Resources/Get.php | 6 +- .../Collections/Attributes/Action.php | 10 +- .../Collections/Attributes/Boolean/Create.php | 6 +- .../Collections/Attributes/Boolean/Update.php | 5 +- .../Attributes/Datetime/Create.php | 7 +- .../Attributes/Datetime/Update.php | 5 +- .../Collections/Attributes/Delete.php | 5 +- .../Collections/Attributes/Email/Create.php | 7 +- .../Collections/Attributes/Email/Update.php | 5 +- .../Collections/Attributes/Enum/Create.php | 7 +- .../Collections/Attributes/Enum/Update.php | 5 +- .../Collections/Attributes/Float/Create.php | 6 +- .../Collections/Attributes/Float/Update.php | 5 +- .../Databases/Collections/Attributes/Get.php | 5 +- .../Collections/Attributes/IP/Create.php | 7 +- .../Collections/Attributes/IP/Update.php | 5 +- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Integer/Update.php | 5 +- .../Collections/Attributes/Line/Create.php | 6 +- .../Collections/Attributes/Line/Update.php | 5 +- .../Collections/Attributes/Point/Create.php | 6 +- .../Collections/Attributes/Point/Update.php | 5 +- .../Collections/Attributes/Polygon/Create.php | 6 +- .../Collections/Attributes/Polygon/Update.php | 5 +- .../Attributes/Relationship/Create.php | 7 +- .../Attributes/Relationship/Update.php | 6 +- .../Collections/Attributes/String/Create.php | 8 +- .../Collections/Attributes/String/Update.php | 6 +- .../Collections/Attributes/URL/Create.php | 7 +- .../Collections/Attributes/URL/Update.php | 6 +- .../Collections/Attributes/XList.php | 5 +- .../Http/Databases/Collections/Create.php | 5 +- .../Http/Databases/Collections/Delete.php | 5 +- .../Collections/Documents/Action.php | 7 +- .../Documents/Attribute/Decrement.php | 13 +- .../Documents/Attribute/Increment.php | 13 +- .../Collections/Documents/Create.php | 43 ++-- .../Collections/Documents/Delete.php | 17 +- .../Databases/Collections/Documents/Get.php | 12 +- .../Collections/Documents/Logs/XList.php | 5 +- .../Collections/Documents/Update.php | 26 ++- .../Collections/Documents/Upsert.php | 26 ++- .../Databases/Collections/Documents/XList.php | 16 +- .../Http/Databases/Collections/Get.php | 5 +- .../Databases/Collections/Indexes/Create.php | 5 +- .../Databases/Collections/Indexes/Delete.php | 5 +- .../Databases/Collections/Indexes/Get.php | 5 +- .../Databases/Collections/Indexes/XList.php | 7 +- .../Http/Databases/Collections/Logs/XList.php | 39 ++-- .../Http/Databases/Collections/Update.php | 5 +- .../Http/Databases/Collections/Usage/Get.php | 5 +- .../Http/Databases/Collections/XList.php | 5 +- .../Http/Databases/Transactions/Create.php | 5 +- .../Transactions/Operations/Create.php | 34 ++-- .../Http/Databases/Transactions/Update.php | 37 ++-- .../Databases/Http/Databases/Usage/Get.php | 5 +- .../Databases/Http/Databases/Usage/XList.php | 5 +- .../Tables/Columns/Boolean/Create.php | 1 - .../Tables/Columns/Boolean/Update.php | 1 - .../Tables/Columns/Datetime/Create.php | 1 - .../Tables/Columns/Datetime/Update.php | 1 - .../Http/TablesDB/Tables/Columns/Delete.php | 1 - .../TablesDB/Tables/Columns/Email/Create.php | 1 - .../TablesDB/Tables/Columns/Email/Update.php | 1 - .../TablesDB/Tables/Columns/Enum/Create.php | 1 - .../TablesDB/Tables/Columns/Enum/Update.php | 1 - .../TablesDB/Tables/Columns/Float/Create.php | 1 - .../TablesDB/Tables/Columns/Float/Update.php | 1 - .../Http/TablesDB/Tables/Columns/Get.php | 1 - .../TablesDB/Tables/Columns/IP/Create.php | 1 - .../TablesDB/Tables/Columns/IP/Update.php | 1 - .../Tables/Columns/Integer/Create.php | 1 - .../Tables/Columns/Integer/Update.php | 1 - .../TablesDB/Tables/Columns/Line/Create.php | 1 - .../TablesDB/Tables/Columns/Line/Update.php | 1 - .../TablesDB/Tables/Columns/Point/Create.php | 1 - .../TablesDB/Tables/Columns/Point/Update.php | 1 - .../Tables/Columns/Polygon/Create.php | 1 - .../Tables/Columns/Polygon/Update.php | 1 - .../Tables/Columns/Relationship/Create.php | 1 - .../Tables/Columns/Relationship/Update.php | 1 - .../TablesDB/Tables/Columns/String/Create.php | 1 - .../TablesDB/Tables/Columns/String/Update.php | 1 - .../TablesDB/Tables/Columns/URL/Create.php | 1 - .../TablesDB/Tables/Columns/URL/Update.php | 1 - .../Http/TablesDB/Tables/Columns/XList.php | 1 - .../Databases/Http/TablesDB/Tables/Create.php | 1 - .../Databases/Http/TablesDB/Tables/Delete.php | 1 - .../Databases/Http/TablesDB/Tables/Get.php | 1 - .../Http/TablesDB/Tables/Indexes/Create.php | 2 - .../Http/TablesDB/Tables/Indexes/Delete.php | 1 - .../Http/TablesDB/Tables/Indexes/Get.php | 1 - .../Http/TablesDB/Tables/Indexes/XList.php | 1 - .../Http/TablesDB/Tables/Logs/XList.php | 1 - .../Http/TablesDB/Tables/Rows/Bulk/Delete.php | 1 - .../Http/TablesDB/Tables/Rows/Bulk/Update.php | 1 - .../Http/TablesDB/Tables/Rows/Bulk/Upsert.php | 1 - .../TablesDB/Tables/Rows/Column/Decrement.php | 1 - .../TablesDB/Tables/Rows/Column/Increment.php | 1 - .../Http/TablesDB/Tables/Rows/Create.php | 1 - .../Http/TablesDB/Tables/Rows/Delete.php | 1 - .../Http/TablesDB/Tables/Rows/Get.php | 1 - .../Http/TablesDB/Tables/Rows/Logs/XList.php | 1 - .../Http/TablesDB/Tables/Rows/Update.php | 1 - .../Http/TablesDB/Tables/Rows/Upsert.php | 1 - .../Http/TablesDB/Tables/Rows/XList.php | 1 - .../Databases/Http/TablesDB/Tables/Update.php | 1 - .../Http/TablesDB/Tables/Usage/Get.php | 1 - .../Databases/Http/TablesDB/Tables/XList.php | 1 - .../Http/TablesDB/Transactions/Create.php | 1 - .../Transactions/Operations/Create.php | 1 - .../Http/TablesDB/Transactions/Update.php | 1 - .../Databases/Http/TablesDB/Usage/Get.php | 1 - .../Databases/Http/TablesDB/Usage/XList.php | 1 - .../Functions/Http/Deployments/Create.php | 5 +- .../Http/Deployments/Template/Create.php | 12 +- .../Functions/Http/Deployments/Vcs/Create.php | 2 +- .../Functions/Http/Executions/Create.php | 25 ++- .../Functions/Http/Executions/Delete.php | 6 +- .../Modules/Functions/Http/Executions/Get.php | 10 +- .../Functions/Http/Executions/XList.php | 10 +- .../Functions/Http/Functions/Create.php | 9 +- .../Functions/Http/Functions/Delete.php | 6 +- .../Http/Functions/Deployment/Update.php | 10 +- .../Functions/Http/Functions/Update.php | 6 +- .../Modules/Functions/Http/Usage/Get.php | 5 +- .../Modules/Functions/Http/Usage/XList.php | 5 +- .../Functions/Http/Variables/Create.php | 6 +- .../Functions/Http/Variables/Delete.php | 6 +- .../Functions/Http/Variables/Update.php | 6 +- .../Modules/Functions/Workers/Builds.php | 8 +- .../Modules/Sites/Http/Deployments/Create.php | 10 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Template/Create.php | 9 +- .../Sites/Http/Deployments/Vcs/Create.php | 6 +- .../Sites/Http/Sites/Deployment/Update.php | 8 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 6 +- .../Modules/Sites/Http/Usage/XList.php | 5 +- .../Storage/Http/Buckets/Files/Create.php | 36 ++-- .../Storage/Http/Buckets/Files/Delete.php | 22 +- .../Http/Buckets/Files/Download/Get.php | 18 +- .../Storage/Http/Buckets/Files/Get.php | 16 +- .../Http/Buckets/Files/Preview/Get.php | 22 +- .../Storage/Http/Buckets/Files/Push/Get.php | 12 +- .../Storage/Http/Buckets/Files/Update.php | 24 +-- .../Storage/Http/Buckets/Files/View/Get.php | 18 +- .../Storage/Http/Buckets/Files/XList.php | 22 +- .../Modules/Storage/Http/Buckets/Get.php | 23 +-- .../Modules/Storage/Http/Buckets/XList.php | 35 ++-- .../Modules/Storage/Http/Usage/Get.php | 5 +- .../Modules/Storage/Http/Usage/XList.php | 5 +- .../Http/Tokens/Buckets/Files/Action.php | 17 +- .../Http/Tokens/Buckets/Files/Create.php | 11 +- .../Http/Tokens/Buckets/Files/XList.php | 6 +- src/Appwrite/Platform/Tasks/Migrate.php | 9 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 3 +- .../Platform/Tasks/StatsResources.php | 5 +- .../Platform/Workers/Certificates.php | 33 +-- src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Platform/Workers/Functions.php | 2 + src/Appwrite/Platform/Workers/Migrations.php | 31 +-- .../Utopia/Database/Documents/User.php | 5 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 5 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 25 +-- .../DatabasesPermissionsGuestTest.php | 25 +-- tests/e2e/Services/Tokens/TokensBase.php | 8 +- .../unit/Messaging/MessagingChannelsTest.php | 18 +- .../Utopia/Database/Documents/UserTest.php | 33 +-- 202 files changed, 978 insertions(+), 1479 deletions(-) diff --git a/app/cli.php b/app/cli.php index 7493d10ab3..07966b2450 100644 --- a/app/cli.php +++ b/app/cli.php @@ -41,6 +41,8 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false)); // require controllers after overwriting runtimes require_once __DIR__ . '/controllers/general.php'; +Authorization::disable(); + CLI::setResource('register', fn () => $register); CLI::setResource('cache', function ($pools) { @@ -58,13 +60,7 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('authorization', function () { - $authorization = new Authorization(); - $authorization->disable(); - return $authorization; -}, []); - -CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { +CLI::setResource('dbForPlatform', function ($pools, $cache) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -78,7 +74,6 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform - ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -104,7 +99,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { } return $dbForPlatform; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); CLI::setResource('console', function () { return new Document(Config::getParam('console')); @@ -115,10 +110,10 @@ CLI::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) { +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -151,7 +146,6 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -168,18 +162,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database - ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); return $database; }; -}, ['pools', 'dbForPlatform', 'cache', 'authorization']); +}, ['pools', 'dbForPlatform', 'cache']); -CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { +CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { + return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -189,7 +182,6 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) @@ -202,7 +194,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); CLI::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); diff --git a/app/config/storage/resource_limits.php b/app/config/storage/resource_limits.php index 43ed2b8b05..cfbcea5a47 100644 --- a/app/config/storage/resource_limits.php +++ b/app/config/storage/resource_limits.php @@ -3,6 +3,4 @@ use Utopia\Image\Image; use Utopia\System\System; -if (\class_exists('Imagick')) { - Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); -} +Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index bcea3387a2..2c481b500c 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -207,10 +207,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr } -$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode, Authorization $authorization) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) { /** @var Appwrite\Utopia\Database\Documents\User $userFromRequest */ - $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -266,7 +266,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -275,7 +275,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - $authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -376,9 +376,8 @@ App::post('/v1/account') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('authorization') ->inject('hooks') - ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Hooks $hooks) { + ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Hooks $hooks) { $email = \strtolower($email); if ('console' === $project->getId()) { @@ -470,9 +469,9 @@ App::post('/v1/account') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -498,9 +497,9 @@ App::post('/v1/account') throw new Exception(Exception::USER_ALREADY_EXISTS); } - $authorization->removeRole(Role::guests()->toString()); - $authorization->addRole(Role::user($user->getId())->toString()); - $authorization->addRole(Role::users()->toString()); + Authorization::unsetRole(Role::guests()->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::users()->toString()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -977,8 +976,7 @@ App::post('/v1/account/sessions/email') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -1023,7 +1021,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) { @@ -1122,8 +1120,7 @@ App::post('/v1/account/sessions/anonymous') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->inject('authorization') - ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1168,7 +1165,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; @@ -1194,7 +1191,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -1277,7 +1274,6 @@ App::post('/v1/account/sessions/token') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') -->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1474,8 +1470,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) { + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1731,7 +1726,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ]); $user->removeAttribute('$sequence'); - $userDoc = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), @@ -1749,8 +1744,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - $authorization->addRole(Role::user($user->getId())->toString()); - $authorization->addRole(Role::users()->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::users()->toString()); if (false === $user->getAttribute('status')) { // Account is blocked $failureRedirect(Exception::USER_BLOCKED); // User is in status blocked @@ -1821,7 +1816,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1845,7 +1840,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2082,8 +2077,7 @@ App::post('/v1/account/tokens/magic-url') ->inject('queueForMails') ->inject('proofForPassword') ->inject('platform') - ->inject('authorization') - ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform, Authorization $authorization) { + ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2156,7 +2150,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); @@ -2176,7 +2170,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2362,8 +2356,7 @@ App::post('/v1/account/tokens/email') ->inject('queueForMails') ->inject('proofForPassword') ->inject('proofForCode') - ->inject('authorization') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2432,9 +2425,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2472,7 +2465,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2669,11 +2662,10 @@ App::put('/v1/account/sessions/magic-url') ->inject('queueForMails') ->inject('store') ->inject('proofForCode') - ->inject('authorization') - ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode, $authorization) use ($createSession) { + ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) { $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); $proofForToken->setHash(new Sha()); - $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode, $authorization); + $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode); }); App::put('/v1/account/sessions/phone') @@ -2719,7 +2711,6 @@ App::put('/v1/account/sessions/phone') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') - ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2763,8 +2754,7 @@ App::post('/v1/account/tokens/phone') ->inject('plan') ->inject('store') ->inject('proofForCode') - ->inject('authorization') - ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2814,9 +2804,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2862,7 +2852,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3253,8 +3243,7 @@ App::patch('/v1/account/email') ->inject('project') ->inject('hooks') ->inject('proofForPassword') - ->inject('authorization') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3306,7 +3295,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ + $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3322,7 +3311,7 @@ App::patch('/v1/account/email') $oldTarget = $user->find('identifier', $oldEmail, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); + Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate) { @@ -3363,9 +3352,8 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') -->inject('authorization') - ->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { + ->inject('proofForPassword') + ->action(function (string $phone, string $password, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3380,7 +3368,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ + $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3411,7 +3399,7 @@ App::patch('/v1/account/phone') $oldTarget = $user->find('identifier', $oldPhone, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); + Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate $th) { @@ -3547,9 +3535,7 @@ App::post('/v1/account/recovery') ->inject('queueForMails') ->inject('queueForEvents') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { - + ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -3585,7 +3571,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3741,8 +3727,7 @@ App::put('/v1/account/recovery') ->inject('hooks') ->inject('proofForPassword') ->inject('proofForToken') -->inject('authorization') - ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ $profile = $dbForProject->getDocument('users', $userId); @@ -3756,7 +3741,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $newPassword = $proofForPassword->hash($password); @@ -3859,8 +3844,7 @@ App::post('/v1/account/verifications/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3889,7 +3873,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4088,10 +4072,9 @@ App::put('/v1/account/verifications/email') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4103,7 +4086,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -4163,8 +4146,7 @@ App::post('/v1/account/verifications/phone') ->inject('queueForStatsUsage') ->inject('plan') ->inject('proofForCode') - ->inject('authorization') - ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -4203,7 +4185,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4309,10 +4291,9 @@ App::put('/v1/account/verifications/phone') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForCode') - ->inject('authorization') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode, Authorization $authorization) { + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4324,7 +4305,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - $authorization->addRole(Role::user($profile->getId())->toString()); + Authorization::setRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -4377,13 +4358,12 @@ App::post('/v1/account/targets/push') ->inject('dbForProject') ->inject('store') ->inject('proofForToken') - ->inject('authorization') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken, Authorization $authorization) { + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); @@ -4458,10 +4438,9 @@ App::put('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { + ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); @@ -4524,9 +4503,8 @@ App::delete('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) { + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index e0cc4181db..baf0ba1512 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -28,12 +28,11 @@ use Utopia\Validator\Text; App::init() ->groups(['graphql']) ->inject('project') - ->inject('authorization') - ->action(function (Document $project, Authorization $authorization) { + ->action(function (Document $project) { if ( array_key_exists('graphql', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['graphql'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index d6388185d3..907ed54de8 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -27,7 +27,6 @@ use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Config\Config; use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -102,8 +101,7 @@ App::get('/v1/health/db') )) ->inject('response') ->inject('pools') - ->inject('authorization') - ->action(action: function (Response $response, Group $pools, Authorization $authorization) { + ->action(function (Response $response, Group $pools) { $output = []; $failures = []; @@ -116,14 +114,14 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); - $adapter->setAuthorization($authorization); + $checkStart = \microtime(true); if ($adapter->ping()) { $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $failures[] = $database; @@ -134,8 +132,6 @@ App::get('/v1/health/db') } } - // Only throw error if ALL databases failed (no successful pings) - // This allows partial failures in environments where not all DBs are ready if (!empty($failures)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); } @@ -185,7 +181,7 @@ App::get('/v1/health/cache') $output[] = new Document([ 'name' => $key . " ($cache)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $failures[] = $cache; @@ -245,7 +241,7 @@ App::get('/v1/health/pubsub') $output[] = new Document([ 'name' => $key . " ($pubsub)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { $failures[] = $pubsub; @@ -827,7 +823,7 @@ App::get('/v1/health/storage/local') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -879,7 +875,7 @@ App::get('/v1/health/storage') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) * 1000) + 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 6ac36fe3c0..0b6a314dc5 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -36,7 +36,6 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -1074,9 +1073,8 @@ App::get('/v1/messaging/providers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1102,7 +1100,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); @@ -2483,9 +2481,8 @@ App::get('/v1/messaging/topics') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2511,7 +2508,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Topic '{$topicId}' for the 'cursor' value not found."); @@ -2785,27 +2782,29 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) { $subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId; - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); } - if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + + $validator = new Authorization('subscribe'); + + if (!$validator->isValid($topic->getAttribute('subscribe'))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2838,7 +2837,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute( + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2883,9 +2882,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2896,7 +2894,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2919,7 +2917,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Subscriber '{$subscriberId}' for the 'cursor' value not found."); @@ -2933,10 +2931,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $authorization) { - return function () use ($subscriber, $dbForProject, $authorization) { - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) { + return function () use ($subscriber, $dbForProject) { + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); return $subscriber ->setAttribute('target', $target) @@ -3069,10 +3067,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Authorization $authorization, Response $response) { - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) { + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3084,8 +3081,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') throw new Exception(Exception::SUBSCRIBER_NOT_FOUND); } - $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber ->setAttribute('target', $target) @@ -3121,10 +3118,9 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { - $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) { + $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3147,7 +3143,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute( + Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3706,9 +3702,8 @@ App::get('/v1/messaging/messages') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') - ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3734,7 +3729,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('messages', $messageId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found."); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 1a17853577..3989ad3298 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -342,7 +342,6 @@ App::post('/v1/migrations/csv/imports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->inject('project') ->inject('platform') ->inject('deviceForFiles') @@ -357,7 +356,6 @@ App::post('/v1/migrations/csv/imports') Response $response, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, Document $project, array $platform, Device $deviceForFiles, @@ -365,7 +363,7 @@ App::post('/v1/migrations/csv/imports') Event $queueForEvents, Migration $queueForMigrations ) { - $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -376,7 +374,7 @@ App::post('/v1/migrations/csv/imports') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $authorization->skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -493,7 +491,6 @@ App::post('/v1/migrations/csv/exports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->inject('project') ->inject('platform') ->inject('queueForEvents') @@ -512,7 +509,6 @@ App::post('/v1/migrations/csv/exports') Response $response, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, Document $project, array $platform, Event $queueForEvents, @@ -524,7 +520,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -537,12 +533,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $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 = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index cda03f923a..a57675d3e8 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -45,10 +45,9 @@ App::get('/v1/project/usage') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('authorization') ->inject('getLogsDB') ->inject('smsRates') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, Authorization $authorization, callable $getLogsDB, array $smsRates) { + ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -103,7 +102,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - $authorization->skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { + Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; @@ -287,7 +286,7 @@ App::get('/v1/project/usage') }, $dbForProject->find('functions')); // This total is includes free and paid SMS usage - $authPhoneTotal = $authorization->skip(fn () => $dbForProject->sum('stats', 'value', [ + $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), @@ -295,7 +294,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = $authorization->skip(fn () => $dbForProject->find('stats', [ + $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index aa67a90885..1f8555b6cd 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -86,17 +86,16 @@ App::post('/v1/teams') ->inject('response') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { + ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAppUser = User::isApp(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)), @@ -492,7 +491,6 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -502,9 +500,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('plan') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { - $isAppUser = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + ->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 $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { + $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -621,13 +619,13 @@ App::post('/v1/teams/:teamId/memberships') ]); try { - $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', $userDocument)); + $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); 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'); @@ -663,11 +661,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - $authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { $membership->setAttribute('secret', $proofForToken->hash($secret)); @@ -679,7 +677,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - $authorization->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } else { throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); @@ -865,8 +863,7 @@ App::get('/v1/teams/:teamId/memberships') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { + ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -936,7 +933,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1007,8 +1004,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { + ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject) { $team = $dbForProject->getDocument('teams', $teamId); @@ -1028,7 +1024,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1107,9 +1103,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1126,9 +1121,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); - $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAppUser = User::isApp(Authorization::getRoles()); + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { // Quick check: fetch up to 2 owners to determine if only one exists @@ -1209,13 +1204,12 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') ->inject('store') ->inject('proofForToken') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1224,7 +1218,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::MEMBERSHIP_NOT_FOUND); } - $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); @@ -1260,11 +1254,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->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))); // Create session for the user if not logged in if (!$hasSession) { - $authorization->addRole(Role::user($user->getId())->toString()); + Authorization::setRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1292,7 +1286,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - $authorization->addRole(Role::user($userId)->toString()); + Authorization::setRole(Role::user($userId)->toString()); $encoded = $store ->setProperty('id', $user->getId()) @@ -1330,7 +1324,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1374,9 +1368,8 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('project') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1434,7 +1427,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members - $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); + Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); } $queueForEvents diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index a963284538..bbe1d8a84a 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2678,8 +2678,8 @@ App::get('/v1/users/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { + ->inject('register') + ->action(function (string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -2689,7 +2689,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 2270f4fd89..4249dbfd48 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -76,7 +76,7 @@ use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Authorization $authorization, Build $queueForBuilds, callable $getProjectDB, Request $request, array $platform) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, array $platform) { $errors = []; foreach ($repositories as $repository) { try { @@ -87,12 +87,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); - $resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -141,7 +141,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -180,7 +180,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } else { @@ -191,7 +191,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = $authorization->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ + $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -212,7 +212,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -251,7 +251,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -294,7 +294,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -334,7 +334,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); - $authorization->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); + Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); @@ -344,7 +344,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -377,7 +377,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -408,7 +408,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -460,7 +460,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if ($lockAcquired) { // Wrap in try/finally to ensure lock file gets deleted try { - $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : ''; @@ -472,7 +472,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()); } } finally { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -1476,12 +1476,11 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') - ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1517,14 +1516,14 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find resourceId from relevant resources table - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push (not committed by us) and not when branch is created or deleted if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1537,16 +1536,16 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - $authorization->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - $authorization->skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -1575,12 +1574,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1589,7 +1588,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1600,7 +1599,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1787,18 +1786,17 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') - ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = $authorization->skip(fn () => $dbForPlatform->findOne('repositories', [ + $repository = Authorization::skip(fn () => $dbForPlatform->findOne('repositories', [ Query::equal('$id', [$repositoryId]), Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1816,7 +1814,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1848,7 +1846,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerCommitMessage = $pullRequestResponse['title'] ?? ''; $providerCommitUrl = $pullRequestResponse['html_url'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index e335f284b7..ec8cfef775 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -59,7 +59,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -67,16 +67,16 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } // TODO: (@Meldiron) Remove after 1.7.x migration - if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); - } else { - $rule = $authorization->skip( - fn () => $dbForPlatform->find('rules', [ - Query::equal('domain', [$host]), - Query::limit(1) - ]) - )[0] ?? new Document(); - } + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $rule = Authorization::skip(function () use ($dbForPlatform, $host, $isMd5) { + if ($isMd5) { + return $dbForPlatform->getDocument('rules', md5($host)); + } + + return $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$host]), + ]) ?? new Document(); + }); $errorView = __DIR__ . '/../views/general/error.phtml'; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -111,7 +111,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = $authorization->skip( + $project = Authorization::skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -119,7 +119,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -158,7 +158,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw /** @var Document $deployment */ if (!empty($rule->getAttribute('deploymentId', ''))) { - $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); } else { // 1.6.x DB schema compatibility // TODO: Make sure deploymentId is never empty, and remove this code @@ -172,15 +172,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // Document of site or function $resource = $resourceType === 'function' ? - $authorization->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : - $authorization->skip(fn () => $dbForProject->getDocument('sites', $resourceId)); + Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : + Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId)); // ID of active deployments // Attempts to use attribute from both schemas (1.6 and 1.7) $activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', '')); // Get deployment document, as intended originally - $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -199,8 +199,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $resource = $type === 'function' ? - $authorization->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : - $authorization->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); + Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); @@ -242,7 +242,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $userExists = false; $userId = $payload['userId'] ?? ''; if (!empty($userId)) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -255,7 +255,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); if (!$project->isEmpty() && isset($user)) { $teamId = $project->getAttribute('teamId', ''); $membership = $user->find('teamId', $teamId, 'memberships'); @@ -862,16 +862,15 @@ App::init() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors) { /* * Appwrite Router */ $hostname = $request->getHostname() ?? ''; $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain - if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (!in_array($hostname, $platformHostnames) || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1034,8 +1033,7 @@ App::init() ->inject('dbForPlatform') ->inject('queueForCertificates') ->inject('platform') - ->inject('authorization') - ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) { + ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform) { $hostname = $request->getHostname(); $cache = Config::getParam('hostnames', []); $platformHostnames = $platform['hostnames'] ?? []; @@ -1063,64 +1061,64 @@ App::init() } // 4. Check/create rule (requires DB access) - $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) { - try { - // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $document = $isMd5 - ? $dbForPlatform->getDocument('rules', md5($domain->get())) - : $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$domain->get()]), - ]); - - if (!$document->isEmpty()) { - return; - } - - // 5. Create new rule - $owner = ''; - $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); - $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - - if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { - $funcDomain = $fallback; - } - - if ( - (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || - (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) - ) { - $owner = 'Appwrite'; - } - - $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); - $document = new Document([ - '$id' => $ruleId, - 'domain' => $domain->get(), - 'type' => 'api', - 'status' => 'verifying', - 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), - 'search' => implode(' ', [$ruleId, $domain->get()]), - 'owner' => $owner, - 'region' => $console->getAttribute('region') + Authorization::disable(); + try { + // TODO: (@Meldiron) Remove after 1.7.x migration + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $document = $isMd5 + ? $dbForPlatform->getDocument('rules', md5($domain->get())) + : $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]), ]); - $dbForPlatform->createDocument('rules', $document); - - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); - $queueForCertificates - ->setDomain($document) - ->setSkipRenewCheck(true) - ->trigger(); - } catch (Duplicate $e) { - Console::info('Certificate already exists'); - } finally { - $cache[$domain->get()] = true; - Config::setParam('hostnames', $cache); + if (!$document->isEmpty()) { + return; } - }); + + // 5. Create new rule + $owner = ''; + $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); + $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { + $funcDomain = $fallback; + } + + if ( + (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || + (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) + ) { + $owner = 'Appwrite'; + } + + $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); + $document = new Document([ + '$id' => $ruleId, + 'domain' => $domain->get(), + 'type' => 'api', + 'status' => 'verifying', + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getSequence(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') + ]); + + $dbForPlatform->createDocument('rules', $document); + + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + $queueForCertificates + ->setDomain($document) + ->setSkipRenewCheck(true) + ->trigger(); + } catch (Duplicate $e) { + Console::info('Certificate already exists'); + } finally { + $cache[$domain->get()] = true; + Config::setParam('hostnames', $cache); + Authorization::reset(); + } }); App::options() @@ -1143,15 +1141,14 @@ App::options() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors) { /* * Appwrite Router */ $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1185,8 +1182,7 @@ App::error() ->inject('log') ->inject('queueForStatsUsage') ->inject('devKey') - ->inject('authorization') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Document $devKey, Authorization $authorization) { + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1268,7 +1264,7 @@ App::error() * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { - if (!DBUser::isPrivileged($authorization->getRoles())) { + if (!DBUser::isPrivileged(Authorization::getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1330,7 +1326,7 @@ App::error() $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', $authorization->getRoles()); + $log->addExtra('roles', Authorization::getRoles()); try { /* add queries to log */ @@ -1534,14 +1530,13 @@ App::get('/robots.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1567,14 +1562,13 @@ App::get('/humans.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1658,8 +1652,7 @@ App::get('/v1/ping') ->inject('project') ->inject('dbForPlatform') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents, Authorization $authorization) { + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { if ($project->isEmpty() || $project->getId() === 'console') { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1671,7 +1664,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - $authorization->skip(function () use ($dbForPlatform, $project) { + Authorization::skip(function () use ($dbForPlatform, $project) { $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 23bbb12183..05c08a2231 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -30,7 +30,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Queue\Publisher; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; @@ -234,8 +233,7 @@ App::init() ->inject('mode') ->inject('team') ->inject('apiKey') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) { + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { $route = $utopia->getRoute(); /** @@ -320,7 +318,7 @@ App::init() // Handle special app role case if ($apiKey->getRole() === User::ROLE_APPS) { // Disable authorization checks for API keys - $authorization->setDefaultStatus(false); + Authorization::setDefaultStatus(false); $user = new User([ '$id' => '', @@ -394,14 +392,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. + Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - $authorization->addRole($role); - foreach ($user->getRoles($authorization) as $authRole) { - $authorization->addRole($authRole); + Authorization::setRole($role); + foreach ($user->getRoles() as $authRole) { + Authorization::setRole($authRole); } // Step 6: Update project and user last activity @@ -409,7 +407,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -444,7 +442,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -511,15 +509,14 @@ App::init() ->inject('devKey') ->inject('telemetry') ->inject('platform') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -549,7 +546,7 @@ App::init() $closestLimit = null; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -660,10 +657,10 @@ App::init() if ($useCache) { $route = $utopia->match($request); $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; - $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged($authorization->getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged(Authorization::getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -680,10 +677,10 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -694,7 +691,8 @@ App::init() } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -705,7 +703,7 @@ App::init() if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -716,11 +714,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!User::isPrivileged($authorization->getRoles())) { + if (!User::isPrivileged(Authorization::getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -816,9 +814,8 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->inject('authorization') ->inject('timelimit') - ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, callable $timelimit) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -979,11 +976,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', 0); $now = DateTime::now(); if ($cacheLog->isEmpty()) { - $authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([ + Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -993,7 +990,7 @@ App::shutdown() ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); - $authorization->skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); + Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); // Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load() $cache->save($key, $data['payload']); } @@ -1005,7 +1002,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!User::isPrivileged($authorization->getRoles())) { + if (!User::isPrivileged(Authorization::getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index c0f7494125..efa733fc34 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -36,8 +36,7 @@ App::init() ->inject('request') ->inject('project') ->inject('geodb') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) { + ->action(function (App $utopia, Request $request, Document $project, Reader $geodb) { $denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', ''); if (!empty($denylist && $project->getId() === 'console')) { $countries = explode(',', $denylist); @@ -50,8 +49,8 @@ App::init() $route = $utopia->match($request); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAppUser = User::isApp(Authorization::getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index 5d08c53eee..b7f857da48 100644 --- a/app/http.php +++ b/app/http.php @@ -27,6 +27,7 @@ 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\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Pools\Group; @@ -260,9 +261,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools); // create appwrite database, `dbForPlatform` is a direct access call. - createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections, $app) { - $authorization = $app->getResource('authorization'); - + createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) { if ($dbForPlatform->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) { $adapter = new AdapterDatabase($dbForPlatform); $audit = new Audit($adapter); @@ -322,9 +321,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } - if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - $authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('screenshots'), '$collection' => ID::custom('buckets'), 'name' => 'Screenshots', @@ -339,7 +338,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); Console::info(" └── Creating files collection for screenshots bucket..."); $files = $collections['buckets']['files'] ?? []; @@ -367,7 +366,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - $authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -459,12 +458,8 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool App::setResource('pools', fn () => $pools); try { - $authorization = $app->getResource('authorization'); - - $request->setAuthorization($authorization); - $response->setAuthorization($authorization); - $authorization->cleanRoles(); - $authorization->addRole(Role::any()->toString()); + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); $app->run($request, $response); } catch (\Throwable $th) { @@ -506,7 +501,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); $log->addExtra('trace', $th->getTraceAsString()); - $log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []); + $log->addExtra('roles', Authorization::getRoles()); $sdk = $route->getLabel("sdk", false); @@ -565,7 +560,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { /** @var Utopia\Database\Database $dbForPlatform */ $dbForPlatform = $app->getResource('dbForPlatform'); - Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) { + Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { try { $time = DateTime::now(); $limit = 1000; @@ -582,8 +577,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $authorization = $app->getResource('authorization'); - $results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries)); + $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); } catch (Throwable $th) { Console::error($th->getMessage()); } diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 2b2e17b6a9..c9ad3fce03 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -4,6 +4,7 @@ use Appwrite\OpenSSL\OpenSSL; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\System\System; Database::addFilter( @@ -69,11 +70,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [ + $attributes = $database->find('attributes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), - ])); + ]); foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); @@ -104,12 +105,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('indexes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), - ])); + ]); } ); @@ -119,11 +120,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('platforms', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -133,12 +134,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('keys', [ Query::equal('resourceType', ['projects']), Query::equal('resourceInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -148,11 +149,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('devKeys', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -162,11 +163,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('webhooks', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -176,7 +177,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database->find('sessions', [ + return Authorization::skip(fn () => $database->find('sessions', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); @@ -189,7 +190,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -203,7 +204,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('challenges', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -217,7 +218,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('authenticators', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -231,7 +232,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -251,14 +252,14 @@ Database::addFilter( default => ['function', 'site'] }; - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('variables', [ Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', $resourceType), Query::orderAsc('resourceType'), Query::orderAsc(), Query::limit(APP_LIMIT_SUBQUERY), - ])); + ]); } ); @@ -294,11 +295,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return $database ->find('variables', [ Query::equal('resourceType', ['project']), Query::limit(APP_LIMIT_SUBQUERY) - ])); + ]); } ); @@ -331,7 +332,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database->getAuthorization()->skip(fn () => $database + return Authorization::skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) @@ -345,7 +346,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $targetIds = $database->getAuthorization()->skip(fn () => \array_map( + $targetIds = Authorization::skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ Query::equal('topicInternalId', [$document->getSequence()]), diff --git a/app/init/resources.php b/app/init/resources.php index 371609da97..a3aa3ae47c 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -230,7 +230,7 @@ App::setResource('allowedSchemes', function (Document $project) { /** * Rule associated with a request origin. */ -App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) { +App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project) { $domain = \parse_url($request->getOrigin(), PHP_URL_HOST); if (empty($domain)) { return new Document(); @@ -238,7 +238,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do // TODO: (@Meldiron) Remove after 1.7.x migration $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = $authorization->skip(function () use ($dbForPlatform, $domain, $isMd5) { + $rule = Authorization::skip(function () use ($dbForPlatform, $domain, $isMd5) { if ($isMd5) { return $dbForPlatform->getDocument('rules', md5($domain)); } @@ -253,7 +253,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do } return $rule; -}, ['request', 'dbForPlatform', 'project', 'authorization']); +}, ['request', 'dbForPlatform', 'project']); /** * CORS service @@ -321,7 +321,7 @@ App::setResource('redirectValidator', function (Document $devKey, array $allowed return new Redirect($allowedHostnames, $allowedSchemes); }, ['devKey', 'allowedHostnames', 'allowedSchemes']); -App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken, $authorization) { +App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) { /** * Handles user authentication and session validation. * @@ -341,7 +341,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co * overwriting the previous value. */ - $authorization->setDefaultStatus(true); + Authorization::setDefaultStatus(true); $store->setKey('a_session_' . $project->getId()); @@ -408,7 +408,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co } // if (APP_MODE_ADMIN === $mode) { // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { - // $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. + // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. // } else { // $user = new Document([]); // } @@ -440,9 +440,9 @@ App::setResource('user', function (string $mode, Document $project, Document $co $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']); -App::setResource('project', function ($dbForPlatform, $request, $console, $authorization) { +App::setResource('project', function ($dbForPlatform, $request, $console) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ @@ -453,10 +453,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console, $autho return $console; } - $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForPlatform', 'request', 'console', 'authorization']); +}, ['dbForPlatform', 'request', 'console']); App::setResource('session', function (User $user, Store $store, Token $proofForToken) { if ($user->isEmpty()) { @@ -479,6 +479,10 @@ App::setResource('session', function (User $user, Store $store, Token $proofForT return; }, ['user', 'store', 'proofForToken']); +App::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + App::setResource('store', function (): Store { return new Store(); }); @@ -509,15 +513,7 @@ App::setResource('proofForCode', function (): Code { return $code; }); -App::setResource('console', function () { - return new Document(Config::getParam('console')); -}, []); - -App::setResource('authorization', function () { - return new Authorization(); -}, []); - -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Authorization $authorization) { +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -533,7 +529,6 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -555,15 +550,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); - -App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { +}, ['pools', 'dbForPlatform', 'cache', 'project']); +App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') @@ -573,12 +566,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authoriz $database->setDocumentType('users', User::class); return $database; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); -App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; - return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -590,15 +583,13 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $configure = (function (Database $database) use ($project, $dsn, $authorization) { + $configure = (function (Database $database) use ($project, $dsn) { $database - ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES) - ->setDocumentType('users', User::class) - ; + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + $database->setDocumentType('users', User::class); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -628,12 +619,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; }; -}, ['pools', 'dbForPlatform', 'cache', 'authorization']); +}, ['pools', 'dbForPlatform', 'cache']); -App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { +App::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $authorization, &$database) { + return function (?Document $project = null) use ($pools, $cache, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int) $project->getSequence()); return $database; @@ -643,7 +634,6 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -656,7 +646,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); App::setResource('audit', function ($dbForProject) { $adapter = new AdapterDatabase($dbForProject); @@ -855,7 +845,7 @@ App::setResource('promiseAdapter', function ($register) { return $register->get('promiseAdapter'); }, ['register']); -App::setResource('schema', function ($utopia, $dbForProject, $authorization) { +App::setResource('schema', function ($utopia, $dbForProject) { $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); @@ -865,8 +855,8 @@ App::setResource('schema', function ($utopia, $dbForProject, $authorization) { return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) { - $attrs = $authorization->skip(fn () => $dbForProject->find('attributes', [ + $attributes = function (int $limit, int $offset) use ($dbForProject) { + $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -940,7 +930,7 @@ App::setResource('schema', function ($utopia, $dbForProject, $authorization) { $urls, $params, ); -}, ['utopia', 'dbForProject', 'authorization']); +}, ['utopia', 'dbForProject']); App::setResource('gitHub', function (Cache $cache) { return new VcsGitHub($cache); @@ -968,7 +958,7 @@ App::setResource('smsRates', function () { return []; }); -App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform, Authorization $authorization) { +App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) { $devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', '')); // Check if given key match project's development keys @@ -987,7 +977,7 @@ App::setResource('devKey', function (Request $request, Document $project, array $accessedAt = $key->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -1004,15 +994,15 @@ App::setResource('devKey', function (Request $request, Document $project, array /** Update access time as well */ $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $key = $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } return $key; -}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']); +}, ['request', 'project', 'servers', 'dbForPlatform']); -App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request, Authorization $authorization) { +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { $teamInternalId = ''; if ($project->getId() !== 'console') { $teamInternalId = $project->getAttribute('teamInternalId', ''); @@ -1022,7 +1012,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A if (str_starts_with($path, '/v1/projects/:projectId')) { $uri = $request->getURI(); $pid = explode('/', $uri)[3]; - $p = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $pid)); + $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); @@ -1031,7 +1021,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -1040,14 +1030,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = $authorization->skip(function () use ($dbForPlatform, $teamInternalId) { + $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ Query::equal('$sequence', [$teamInternalId]), ]); }); return $team; -}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']); +}, ['project', 'dbForPlatform', 'utopia', 'request']); App::setResource( 'isResourceBlocked', @@ -1085,7 +1075,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key App::setResource('executor', fn () => new Executor()); -App::setResource('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) { +App::setResource('resourceToken', function ($project, $dbForProject, $request) { $tokenJWT = $request->getParam('token'); if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication @@ -1103,7 +1093,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A return new Document([]); } - $token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -1121,7 +1111,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A } return match ($token->getAttribute('resourceType')) { - TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject, $authorization) { + TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { $sequences = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); @@ -1132,7 +1122,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A $accessedAt = $token->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) { $token->setAttribute('accessedAt', DatabaseDateTime::now()); - $authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); + Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ @@ -1147,8 +1137,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A }; } return new Document([]); -}, ['project', 'dbForProject', 'request', 'authorization']); +}, ['project', 'dbForProject', 'request']); -App::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) { - return new TransactionState($dbForProject, $authorization); -}, ['dbForProject', 'authorization']); +App::setResource('transactionState', function (Database $dbForProject) { + return new TransactionState($dbForProject); +}, ['dbForProject']); diff --git a/app/realtime.php b/app/realtime.php index 31e6015d92..fab0ce7561 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -32,6 +32,7 @@ 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\DSN\DSN; use Utopia\Logger\Log; use Utopia\Pools\Group; @@ -308,7 +309,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume 'value' => '{}' ]); - $statsDocument = $database->getAuthorization()->skip(fn () => $database->createDocument('realtime', $document)); + $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); break; } catch (Throwable) { Console::warning("Collection not ready. Retrying connection ({$attempts})..."); @@ -338,7 +339,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume ->setAttribute('timestamp', DateTime::now()) ->setAttribute('value', json_encode($payload)); - $database->getAuthorization()->skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); + Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (Throwable $th) { $logError($th, "updateWorkerDocument"); } @@ -369,7 +370,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $payload = []; - $list = $database->getAuthorization()->skip(fn () => $database->find('realtime', [ + $list = Authorization::skip(fn () => $database->find('realtime', [ Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)), ])); @@ -463,13 +464,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) { $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId])); $consoleDatabase = getConsoleDB(); - $project = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); /** @var Appwrite\Utopia\Database\Documents\User $user */ $user = $database->getDocument('users', $userId); - $roles = $user->getRoles($database->getAuthorization()); + $roles = $user->getRoles(); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -525,7 +526,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); - $authorization = $app->getResource('authorization'); /* * Project Check @@ -537,7 +537,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -573,7 +573,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = $user->getRoles($authorization); + $roles = $user->getRoles(); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -586,8 +586,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $realtime->subscribe($project->getId(), $connection, $roles, $channels); - $realtime->connections[$connection]['authorization'] = $authorization; - $user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ @@ -616,7 +614,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $code = 500; } - $message = $th->getMessage(); // sanitize 0 && 5xx errors @@ -646,19 +643,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) { try { $response = new Response(new SwooleResponse()); - $projectId = $realtime->connections[$connection]['projectId'] ?? null; - - // Get authorization from connection (stored during onOpen) - $authorization = $realtime->connections[$connection]['authorization'] ?? null; - + $projectId = $realtime->connections[$connection]['projectId']; $database = getConsoleDB(); - $database->setAuthorization($authorization); if ($projectId !== 'console') { - $project = $authorization->skip(fn () => $database->getDocument('projects', $projectId)); - + $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); $database = getProjectDB($project); - $database->setAuthorization($authorization); } else { $project = null; } @@ -722,19 +712,10 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = $user->getRoles($database->getAuthorization()); + $roles = $user->getRoles(); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); - - // Preserve authorization before subscribe overwrites the connection array - $authorization = $realtime->connections[$connection]['authorization'] ?? null; - $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); - // Restore authorization after subscribe - if ($authorization !== null) { - $realtime->connections[$connection]['authorization'] = $authorization; - } - $user = $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ 'type' => 'response', diff --git a/app/worker.php b/app/worker.php index d31e63fc8b..3720fb85fe 100644 --- a/app/worker.php +++ b/app/worker.php @@ -49,30 +49,19 @@ use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; +Authorization::disable(); Runtime::enableCoroutine(); Server::setResource('register', fn () => $register); -Server::setResource('authorization', function () { - $authorization = new Authorization(); - $authorization->disable(); - return $authorization; -}, []); - -Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, Authorization $authorization) { +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); $adapter = new DatabasePool($pools->get('console')); $dbForPlatform = new Database($adapter, $cache); - - $dbForPlatform - ->setAuthorization($authorization) - ->setNamespace('_console') - ->setDocumentType('users', User::class) - ; - - + $dbForPlatform->setNamespace('_console'); + $dbForPlatform->setDocumentType('users', User::class); return $dbForPlatform; -}, ['cache', 'register', 'authorization']); +}, ['cache', 'register']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -85,7 +74,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform, Authorization $authorization) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -117,17 +106,15 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getSequence()); } - $database - ->setAuthorization($authorization) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform', 'authorization']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -141,7 +128,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - $database->setAuthorization($authorization); + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -178,17 +165,15 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf ->setNamespace('_' . $project->getSequence()); } - $database - ->setAuthorization($authorization) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; }; -}, ['pools', 'dbForPlatform', 'cache', 'authorization']); +}, ['pools', 'dbForPlatform', 'cache']); -Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { +Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { + return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -198,7 +183,6 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authoriza $database = new Database($adapter, $cache); $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER) @@ -211,7 +195,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authoriza return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day @@ -530,8 +514,7 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->inject('authorization') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, Authorization $authorization) use ($worker, $queueName) { + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); if ($logger) { @@ -547,7 +530,7 @@ $worker $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', $authorization->getRoles()); + $log->addExtra('roles', Authorization::getRoles()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/composer.json b/composer.json index f5bab03697..a9c67ede2e 100644 --- a/composer.json +++ b/composer.json @@ -45,14 +45,14 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.19.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "1.*", + "utopia-php/abuse": "1.*.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "2.*", + "utopia-php/audit": "2.0.2-rc3", "utopia-php/auth": "0.5.*", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", - "utopia-php/config": "1.*", - "utopia-php/database": "4.*", + "utopia-php/config": "1.*.*", + "utopia-php/database": "3.*.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.11.*", "utopia-php/emails": "0.6.*", @@ -64,7 +64,7 @@ "utopia-php/locale": "0.8.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.20.*", - "utopia-php/migration": "1.*", + "utopia-php/migration": "1.3.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 6fead373dd..11b00ab631 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": "33da844fdf5648d1d1a027dfb6ae42bc", + "content-hash": "0644a7889caffed39ba2c9c5189e45fe", "packages": [ { "name": "adhocore/jwt", @@ -3455,24 +3455,25 @@ }, { "name": "utopia-php/abuse", - "version": "1.0.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" + "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", - "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/3339d057c6bb1fa3e5ac5b2598923f6938425ec2", + "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2", "shasum": "" }, "require": { + "appwrite/appwrite": "19.*.*", "ext-curl": "*", "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "*" + "utopia-php/database": "3.*.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3500,9 +3501,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/1.0.2" + "source": "https://github.com/utopia-php/abuse/tree/1.2.0" }, - "time": "2025-10-20T07:18:33+00:00" + "time": "2026-01-05T21:29:10+00:00" }, { "name": "utopia-php/analytics", @@ -3552,23 +3553,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.4", + "version": "2.0.2-rc3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7" + "reference": "f60a298b516300f56a328403b334b7d62a96e7e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/1301ab2607667b9f86456f86895f3e26f8c0c9a7", - "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7", + "reference": "f60a298b516300f56a328403b334b7d62a96e7e7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "4.*", + "utopia-php/database": "3.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.2.*" + "utopia-php/validators": "0.1.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3595,9 +3596,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.4" + "source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3" }, - "time": "2026-01-14T07:22:46+00:00" + "time": "2026-01-06T15:32:52+00:00" }, { "name": "utopia-php/auth", @@ -3898,16 +3899,16 @@ }, { "name": "utopia-php/database", - "version": "4.5.1", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898" + "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", - "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", + "url": "https://api.github.com/repos/utopia-php/database/zipball/c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", + "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", "shasum": "" }, "require": { @@ -3950,9 +3951,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.5.1" + "source": "https://github.com/utopia-php/database/tree/3.6.1" }, - "time": "2026-01-14T12:07:24+00:00" + "time": "2025-12-16T09:55:41+00:00" }, { "name": "utopia-php/detector", @@ -4266,23 +4267,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.37", + "version": "0.33.36", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "30a119d76531d89da9240496940c84fcd9e1758b" + "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", - "reference": "30a119d76531d89da9240496940c84fcd9e1758b", + "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", + "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.2.*" + "utopia-php/validators": "0.1.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4308,9 +4309,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.37" + "source": "https://github.com/utopia-php/http/tree/0.33.36" }, - "time": "2026-01-13T10:10:21+00:00" + "time": "2026-01-12T07:32:29+00:00" }, { "name": "utopia-php/image", @@ -4515,16 +4516,16 @@ }, { "name": "utopia-php/migration", - "version": "1.4.3", + "version": "1.3.13", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" + "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", - "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/c5e3f5e970e62e8f7db97b5b90baae2af800a715", + "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715", "shasum": "" }, "require": { @@ -4533,7 +4534,7 @@ "ext-openssl": "*", "php": ">=8.1", "utopia-php/console": "0.0.*", - "utopia-php/database": "4.*", + "utopia-php/database": "3.*", "utopia-php/dsn": "0.2.*", "utopia-php/storage": "0.18.*" }, @@ -4564,9 +4565,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.4.3" + "source": "https://github.com/utopia-php/migration/tree/1.3.13" }, - "time": "2026-01-13T09:51:08+00:00" + "time": "2026-01-07T14:48:05+00:00" }, { "name": "utopia-php/mongo", @@ -5056,22 +5057,22 @@ }, { "name": "utopia-php/swoole", - "version": "1.0.0", + "version": "0.8.6", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "95a937acb393dbf95cccba239d55886e2848ab0b" + "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/95a937acb393dbf95cccba239d55886e2848ab0b", - "reference": "95a937acb393dbf95cccba239d55886e2848ab0b", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", + "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.37" + "utopia-php/framework": "0.33.36" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5101,9 +5102,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/1.0.0" + "source": "https://github.com/utopia-php/swoole/tree/0.8.6" }, - "time": "2026-01-14T14:00:11+00:00" + "time": "2026-01-12T07:57:35+00:00" }, { "name": "utopia-php/system", @@ -5213,16 +5214,16 @@ }, { "name": "utopia-php/validators", - "version": "0.2.0", + "version": "0.1.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" + "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", - "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", + "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", "shasum": "" }, "require": { @@ -5230,7 +5231,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "2.*", + "phpstan/phpstan": "1.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5252,9 +5253,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.2.0" + "source": "https://github.com/utopia-php/validators/tree/0.1.0" }, - "time": "2026-01-13T09:16:51+00:00" + "time": "2025-11-18T11:05:46+00:00" }, { "name": "utopia-php/vcs", @@ -8987,7 +8988,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/audit": 5 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 8e098774e6..23dc6fc2e9 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -20,12 +20,10 @@ use Utopia\Database\Validator\Authorization; class TransactionState { private Database $dbForProject; - private Authorization $authorization; - /** @var Authorization $authorization */ - public function __construct(Database $dbForProject, Authorization $authorization) + + public function __construct(Database $dbForProject) { $this->dbForProject = $dbForProject; - $this->authorization = $authorization; } @@ -344,12 +342,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = $this->authorization->skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') { return []; } - $operations = $this->authorization->skip(fn () => $this->dbForProject->find('transactionLogs', [ + $operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index ea51225ba6..bc37924db6 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -100,6 +100,8 @@ abstract class Migration public function __construct() { + Authorization::disable(); + Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -127,7 +129,6 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -135,9 +136,6 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; - $authorization->disable(); - $authorization->setDefaultStatus(false); - return $this; } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index bf7d01764f..1ff2f8f706 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -21,7 +21,7 @@ class Action extends PlatformAction return \dirname(__DIR__, 6); } - protected function avatar(string $type, string $code, int $width, int $height, int $quality, Response $response): void + protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response): void { $code = \strtolower($code); $type = \strtolower($type); @@ -58,10 +58,10 @@ class Action extends PlatformAction unset($image); } - protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array + protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger): array { try { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -112,7 +112,7 @@ class Action extends PlatformAction ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - $authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); + Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -120,7 +120,7 @@ class Action extends PlatformAction do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php index 637ea647ef..04648752b5 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatar('browsers', $code, $width, $height, $quality, $response); + $this->avatarCallback('browsers', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index a6a013ef21..1c0de4001e 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -53,13 +53,12 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -69,7 +68,7 @@ class Get extends Action $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index f8e7a35b05..9d53991dd6 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -53,13 +53,12 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -70,7 +69,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index 37776a3466..f7c983db78 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -53,13 +53,12 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) { - $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -74,7 +73,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php index 87357f14c7..5d3429b377 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatar('credit-cards', $code, $width, $height, $quality, $response); + $this->avatarCallback('credit-cards', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php index 8230b15f50..c3960c134e 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatar('flags', $code, $width, $height, $quality, $response); + $this->avatarCallback('flags', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 33b69dd589..47afc90986 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -13,7 +13,6 @@ 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\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; @@ -143,7 +142,7 @@ class Base extends Action return $deployment; } - public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = ''): Document + public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document { $deploymentId = ID::unique(); $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); @@ -240,7 +239,7 @@ class Base extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -266,7 +265,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -303,7 +302,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -329,8 +328,6 @@ class Base extends Action } } - $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); - $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) @@ -339,34 +336,4 @@ class Base extends Action return $deployment; } - - /** - * Update empty manual rule for deployment. - * In case of first deployment, deployment ID will be empty in the rules, so we need to update it here. - * - * @param \Utopia\Database\Document $project - * @param \Utopia\Database\Document $resource - * @param \Utopia\Database\Document $deployment - * @param \Utopia\Database\Database $dbForPlatform - * @return void - */ - public static function updateEmptyManualRule(Document $project, Document $resource, Document $deployment, Database $dbForPlatform, Authorization $authorization) - { - $resourceType = $resource->getCollection() === 'sites' ? 'site' : 'function'; - - $queries = [ - Query::equal('projectInternalId', [$project->getSequence()]), - Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), - Query::equal('deploymentResourceType', [$resourceType]), - Query::equal('deploymentId', ['']), - Query::equal('type', ['deployment']), - Query::equal('trigger', ['manual']), - ]; - $dbForPlatform->forEach('rules', function (Document $rule) use ($deployment, $dbForPlatform, $authorization) { - $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([ - 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), - ]))); - }, $queries); - } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 1468bf71ac..aa43b12125 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -60,7 +60,6 @@ class Get extends Action ->inject('response') ->inject('dbForPlatform') ->inject('platform') - ->inject('authorization') ->callback($this->action(...)); } @@ -69,8 +68,7 @@ class Get extends Action string $type, Response $response, Database $dbForPlatform, - array $platform, - Authorization $authorization, + array $platform ) { $domains = $platform['hostnames'] ?? []; if ($type === 'rules') { @@ -123,7 +121,7 @@ class Get extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $document = $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ + $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$value]), ])); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index e2df5d92e6..83a401a35e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -292,7 +292,7 @@ abstract class Action extends UtopiaAction }; } - protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): Document + protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document { $key = $attribute->getAttribute('key'); $type = $attribute->getAttribute('type', ''); @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException(), params: [$type]); } - $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, params: [$databaseId]); @@ -371,7 +371,7 @@ abstract class Action extends UtopiaAction \in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) && $attribute->getAttribute('required') ) { - $hasData = !$authorization->skip(fn () => $dbForProject + $hasData = !Authorization::skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -472,9 +472,9 @@ abstract class Action extends UtopiaAction return $attribute; } - protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document + protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index 442461fdd3..f04532aeee 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,11 +69,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -83,7 +81,7 @@ class Create extends Action 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 92324aae70..003b4227c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,11 +68,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -81,7 +79,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_BOOLEAN, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index bd3108a871..c2982445a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute( $databaseId, @@ -92,8 +90,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index 2518875424..984d4b0245 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_DATETIME, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 37ae2a7bfe..649cde10aa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -67,13 +67,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index a36e264e50..b36072eb75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute( $databaseId, @@ -92,8 +90,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 609a337625..382f16b469 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_EMAIL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 3c47d1fdfe..9145191b0c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,11 +73,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { if (!is_null($default) && !\in_array($default, $elements, true)) { throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); @@ -100,8 +98,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 5bea5230c0..2f47eb0cc6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,11 +71,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -84,7 +82,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_ENUM, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 0dc11bd76c..56d8874794 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -75,11 +74,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $min ??= -PHP_FLOAT_MAX; $max ??= PHP_FLOAT_MAX; @@ -102,7 +100,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 20b5c0767d..330c649f27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,11 +71,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -84,7 +82,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_FLOAT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 436b22c6c9..3a8eece531 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -68,13 +68,12 @@ class Get extends Action ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 2adf3977f4..2340d1d55d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute( $databaseId, @@ -92,8 +90,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index eccf18b005..236dbf7f83 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_IP, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 0989bb2904..1be4df10c7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -75,11 +74,10 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $min ??= \PHP_INT_MIN; $max ??= \PHP_INT_MAX; @@ -104,7 +102,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 57797d3e03..ebb275ae63 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,11 +71,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -84,7 +82,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_INTEGER, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index fc846957b0..f0fd728902 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,18 +69,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_LINESTRING, 'required' => $required, 'default' => $default - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 8fff545921..3407da2b34 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_LINESTRING, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index a89c21581d..f2e4d19267 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,18 +69,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POINT, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index 9561fe6b96..86e78e56e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_POINT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 54da3ac604..4c49b21050 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,18 +69,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POLYGON, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index b82a3d4be0..0dbb117cec 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -70,11 +69,10 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,7 +80,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_POLYGON, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index 615e64dfd7..b43568a968 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -83,17 +83,16 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $key ??= $relatedCollectionId; $twoWayKeyWasProvided = $twoWayKey !== null; $twoWayKey ??= $collectionId; - $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, params: [$databaseId]); } @@ -155,7 +154,7 @@ class Create extends Action 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, ] - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); foreach ($attribute->getAttribute('options', []) as $k => $option) { $attribute->setAttribute($k, $option); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index d180131a44..feed58a4ff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,7 +71,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -84,8 +82,7 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -93,7 +90,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_RELATIONSHIP, required: false, options: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index b3fe03cace..b42558f063 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -14,7 +14,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -78,7 +77,6 @@ class Create extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -95,8 +93,7 @@ class Create extends Action Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, - array $plan, - Authorization $authorization + array $plan ): void { if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.'); @@ -135,8 +132,7 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents, - $authorization + $queueForEvents ); $attribute->setAttribute('encrypt', $encrypt); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 37547f3da8..53ea2a0e03 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -73,7 +72,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -87,8 +85,7 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -96,7 +93,6 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, - authorization: $authorization, type: Database::VAR_STRING, size: $size, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index ed1a23acf5..7529845016 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,7 +70,6 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -85,8 +83,7 @@ class Create extends Action UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -96,7 +93,7 @@ class Create extends Action 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 08f7a26fd9..9ba8ebb859 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,7 +69,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -83,8 +81,7 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ): void { $attribute = $this->updateAttribute( $databaseId, @@ -92,7 +89,6 @@ class Update extends Action $key, $dbForProject, $queueForEvents, - $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_URL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 61c5b295cf..6bfe5f8913 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -64,13 +64,12 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 89cc14056a..724f40f00e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -85,13 +85,12 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index fd2c419954..af36649061 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -64,13 +64,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index ec65135a05..f16d00998d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -258,9 +258,9 @@ abstract class Action extends DatabasesAction Document $collection, Document $document, Database $dbForProject, + /* options */ array &$collectionsCache, - Authorization $authorization, ?int &$operations = null, ): bool { @@ -297,7 +297,7 @@ abstract class Action extends DatabasesAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = $authorization->skip( + $relatedCollectionDoc = Authorization::skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId @@ -323,8 +323,7 @@ abstract class Action extends DatabasesAction document: $relation, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations, - authorization: $authorization + operations: $operations ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 16b7bd1b25..53831f0fc5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -85,21 +85,20 @@ class Decrement extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $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, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -107,7 +106,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index 7adae7633b..ea680db3b1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -85,21 +85,20 @@ class Increment extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $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, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -107,7 +106,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index bbc63da499..6ec06f5c8a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -24,7 +24,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -133,10 +132,9 @@ class Create extends Action ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $data = \is_string($data) ? \json_decode($data, true) @@ -180,19 +178,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -206,7 +204,7 @@ class Create extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext()); } - $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) { + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, @@ -249,8 +247,8 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')'); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); } } } @@ -261,25 +259,21 @@ class Create extends Action $operations = 0; - $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations, $authorization) { + $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations) { $operations++; $documentSecurity = $collection->getAttribute('documentSecurity', false); + $validator = new Authorization($permission); - $validCollection = $authorization->isValid( - new Input($permission, $collection->getPermissionsByType($permission)) - ); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $valid = $validator->isValid($collection->getPermissionsByType($permission)); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($permission === Database::PERMISSION_UPDATE) { - $validDocument = $authorization->isValid( - new Input($permission, $document->getUpdate()) - ); - $valid = $validCollection || $validDocument; + $valid = $valid || $validator->isValid($document->getUpdate()); if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } } @@ -304,7 +298,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization->skip( + $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -320,7 +314,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = $authorization->skip( + $current = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -375,7 +369,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -474,7 +468,6 @@ class Create extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 7acf8e386e..faae638c88 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -83,7 +83,6 @@ class Delete extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -98,19 +97,18 @@ class Delete extends Action Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, - array $plan, - Authorization $authorization + array $plan ): void { - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -123,7 +121,7 @@ class Delete extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -133,7 +131,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -207,7 +205,6 @@ class Delete extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization ); $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index cb8b0dd42e..f560267d4b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -70,21 +70,20 @@ class Get extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -126,7 +125,6 @@ class Get extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization, operations: $operations ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index 2f5579f0ca..a4dd38ef67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -72,14 +72,13 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index a92d8ec180..707857347a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -87,11 +87,10 @@ class Update extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -99,16 +98,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -126,7 +125,7 @@ class Update extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -141,7 +140,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -154,7 +153,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -172,7 +171,7 @@ class Update extends Action $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { $operations++; $relationships = \array_filter( @@ -196,7 +195,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization->skip( + $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -213,7 +212,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -250,7 +249,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -341,7 +340,6 @@ class Update extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization, ); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index 62e59dd010..b32871add2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -91,11 +91,10 @@ class Upsert extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -107,15 +106,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -140,7 +139,7 @@ class Upsert extends Action // Use transaction-aware document retrieval to see changes from same transaction $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -156,7 +155,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -169,7 +168,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -182,7 +181,7 @@ class Upsert extends Action $newDocument = new Document($data); $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { $operations++; $relationships = \array_filter( @@ -206,7 +205,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization->skip( + $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -223,7 +222,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -260,7 +259,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -362,7 +361,6 @@ class Upsert extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization ); $relationships = \array_map( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index ff94e67b02..8b770284c3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -74,21 +74,20 @@ class XList extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -116,7 +115,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); @@ -162,8 +161,7 @@ class XList extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - authorization: $authorization, - operations: $operations + operations: $operations, ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index d8df8f1f8c..e7909772a5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -57,13 +57,12 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 5b035a8688..872b7348fe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -79,13 +79,12 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index d9f9f66504..27b28e866c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -70,13 +70,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index 661f259910..d66bf8f38f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -59,13 +59,12 @@ class Get extends Action ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 90826ffbe3..abbdefb4d5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -66,14 +66,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { /** @var Document $database */ - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); @@ -113,7 +112,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 0b6e47a798..0f5a57c6e9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -71,14 +71,13 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void { - $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, params: [$databaseId]); @@ -113,9 +112,9 @@ class XList extends Action $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - $os = $detector->getOS() ?: []; - $client = $detector->getClient() ?: []; - $device = $detector->getDevice() ?: []; + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); $output[$i] = new Document([ 'event' => $log['event'], @@ -123,20 +122,20 @@ class XList extends Action 'userEmail' => $log['data']['userEmail'] ?? null, 'userName' => $log['data']['userName'] ?? null, 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'] ?? null, - 'time' => $log['time'] ?? null, - 'osCode' => $os['osCode'] ?? null, - 'osName' => $os['osName'] ?? null, - 'osVersion' => $os['osVersion'] ?? null, - 'clientType' => $client['clientType'] ?? null, - 'clientCode' => $client['clientCode'] ?? null, - 'clientName' => $client['clientName'] ?? null, - 'clientVersion' => $client['clientVersion'] ?? null, - 'clientEngine' => $client['clientEngine'] ?? null, - 'clientEngineVersion' => $client['clientEngineVersion'] ?? null, - 'deviceName' => $device['deviceName'] ?? null, - 'deviceBrand' => $device['deviceBrand'] ?? null, - 'deviceModel' => $device['deviceModel'] ?? null + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'] ]); $record = $geodb->get($log['ip']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index 304ce5c88e..e319a33e67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -71,13 +71,12 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index 0552a31509..c4a46650c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -63,11 +63,10 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { $database = $dbForProject->getDocument('databases', $databaseId); $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); @@ -84,7 +83,7 @@ class Get extends Action str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index c23286f3cd..b0b0385bf5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -67,13 +67,12 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { - $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php index 4ca20f8414..20c71223c6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -55,11 +55,10 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('user') - ->inject('authorization') ->callback($this->action(...)); } - public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, Authorization $authorization): void + public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user): void { $permissions = []; if (!empty($user->getId())) { @@ -74,7 +73,7 @@ class Create extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->createDocument('transactions', new Document([ + $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ '$id' => ID::unique(), '$permissions' => $permissions, 'status' => 'pending', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php index f09ed2bc27..5a2568db0c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -18,7 +18,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -64,22 +63,21 @@ class Create extends Action ->inject('dbForProject') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization): void + public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan): void { if (empty($operations)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -115,13 +113,13 @@ class Create extends Action throw new Exception(Exception::USER_UNAUTHORIZED); } - $database = $databases[$operation['databaseId']] ??= $authorization->skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); + $database = $databases[$operation['databaseId']] ??= Authorization::skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$operation['databaseId']]); } $collection = $collections[$operation[$this->getGroupId()]] ??= - $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND, params: [$operation[$this->getGroupId()]]); @@ -167,20 +165,14 @@ class Create extends Action // For individual operations, enforce permissions unless using API key/admin if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - - $collectionValid = $authorization->isValid( - new Input($permissionType, $collection->getPermissionsByType($permissionType)) - ); + $validator = new Authorization($permissionType); + $collectionValid = $validator->isValid($collection->getPermissionsByType($permissionType)); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $authorization->isValid( - new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) - ); + $documentValid = $validator->isValid($document->getUpdate()); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $authorization->isValid( - new Input(Database::PERMISSION_DELETE, $document->getDelete()) - ); + $documentValid = $validator->isValid($document->getDelete()); } } @@ -197,7 +189,7 @@ class Create extends Action // Users can only set permissions for roles they have if (isset($operation['data']['$permissions'])) { $permissions = $operation['data']['$permissions']; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -209,7 +201,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -238,7 +230,7 @@ class Create extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { $dbForProject->createDocuments('transactionLogs', $staged); return $dbForProject->increaseDocumentAttribute( 'transactions', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php index e4f1051464..9235c81b8e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -76,7 +76,6 @@ class Update extends Action ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') - ->inject('authorization') ->callback($this->action(...)); } @@ -103,7 +102,7 @@ class Update extends Action * @throws Structure * @throws \Utopia\Exception */ - public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization): void + public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void { if (!$commit && !$rollback) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); @@ -112,11 +111,11 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -139,12 +138,12 @@ class Update extends Action $currentDocumentId = null; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -168,7 +167,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = $authorization->skip( + $collections[$collectionId] = Authorization::skip( fn () => $dbForProject->getCollection($collectionId) ); } @@ -233,7 +232,7 @@ class Update extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -244,33 +243,33 @@ class Update extends Action ->setDocument($transaction); }); } catch (NotFoundException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e, params: [$currentDocumentId ?? 'unknown']); } catch (DuplicateException | ConflictException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_CONFLICT, previous: $e); } catch (StructureException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (LimitException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, $e->getMessage()); } catch (TransactionException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_FAILED, $e->getMessage()); } catch (QueryException $e) { - $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); @@ -298,11 +297,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = $authorization->skip(fn () => $dbForProject->findOne('databases', [ + $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = $authorization->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -394,7 +393,7 @@ class Update extends Action } if ($rollback) { - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'failed']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index a1aa7a70b8..a717b00ae4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -59,11 +59,10 @@ class Get extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void { $database = $dbForProject->getDocument('databases', $databaseId); @@ -82,7 +81,7 @@ class Get extends Action str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 757f845c68..c13149cfc7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -56,11 +56,10 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void + public function action(string $range, UtopiaResponse $response, Database $dbForProject): void { $periods = Config::getParam('usage', []); @@ -75,7 +74,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php index eede1b221b..c0d502d10a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php @@ -60,7 +60,6 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php index cd8d392cfc..c5939b6974 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php @@ -61,7 +61,6 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php index 79722efee1..63693abb67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php @@ -62,7 +62,6 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php index c39681a743..b022d0ed85 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php @@ -63,7 +63,6 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php index da63b0cef7..8a691a6e98 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php @@ -58,7 +58,6 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php index 51e7f295a1..6d19f99b7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php @@ -61,7 +61,6 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php index daca13d587..48a04304bd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php @@ -62,7 +62,6 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php index 4d5881c81e..bd280a2910 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php @@ -64,7 +64,6 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php index 122671adc5..ac5c1cf907 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php @@ -65,7 +65,6 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php index cd898fa0bf..8293d66992 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php @@ -63,7 +63,6 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php index ee9c5f6cb1..bf2815db45 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php @@ -64,7 +64,6 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php index 39dafbd1a6..ee88ac8683 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php @@ -61,7 +61,6 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php index 80c764b4c5..9b38cd9dfd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php @@ -61,7 +61,6 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php index 54ed029c71..7db8625ebf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php @@ -62,7 +62,6 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index f590e8bdbb..a29d728437 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -63,7 +63,6 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index 83b6f1bfc6..7621dc6dda 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -64,7 +64,6 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php index 227fece7de..6110d6ee07 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php @@ -61,7 +61,6 @@ class Create extends LineCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php index b0e433da5f..afd0098152 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php @@ -63,7 +63,6 @@ class Update extends LineUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php index 3fc5865905..084adca860 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php @@ -61,7 +61,6 @@ class Create extends PointCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 040b8171d7..632be85871 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php @@ -63,7 +63,6 @@ class Update extends PointUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php index 630340ba7b..723940af58 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php @@ -61,7 +61,6 @@ class Create extends PolygonCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 43b4a4e6a4..91b55f74b4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php @@ -63,7 +63,6 @@ class Update extends PolygonUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php index 7f28a3cdb7..f3933160c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php @@ -73,7 +73,6 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index fd7fdab8de..eb87713457 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php @@ -65,7 +65,6 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php index ff50313a7c..9279409e88 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php @@ -66,7 +66,6 @@ class Create extends StringCreate ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 6ad1be124b..9fffa71b33 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php @@ -65,7 +65,6 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php index b19d6e80a2..50f5ea5d5b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php @@ -61,7 +61,6 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index dce11964e8..b52ea66ce1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php @@ -62,7 +62,6 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 13ebe14682..39551e5113 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -52,7 +52,6 @@ class XList extends AttributesXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php index bd08ad5617..7287c2cb3e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -67,7 +67,6 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php index 925a7b2494..d4af8b3508 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php @@ -55,7 +55,6 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php index ad83291815..4286ee07ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php @@ -50,7 +50,6 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index 09720f4d71..727334b6da 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php @@ -66,8 +66,6 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php index 7fa8073d1e..7d187ab5a1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php @@ -61,7 +61,6 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php index 246d569825..75ee507aa8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php @@ -52,7 +52,6 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index 1dc2d3ea43..bf5f27e388 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -54,7 +54,6 @@ class XList extends IndexXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php index 79691436e4..5eab050b7e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php @@ -50,7 +50,6 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php index b9896d282d..accb0392fe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php @@ -66,7 +66,6 @@ class Delete extends DocumentsDelete ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php index f4ccea1698..fea59b8b13 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php @@ -68,7 +68,6 @@ class Update extends DocumentsUpdate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php index 69a687d92f..492af25e9f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php @@ -68,7 +68,6 @@ class Upsert extends DocumentsUpsert ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php index a660b008e1..42f2919ce1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php @@ -67,7 +67,6 @@ class Decrement extends DecrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php index c2b69429ce..3d04d71c26 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php @@ -67,7 +67,6 @@ class Increment extends IncrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php index c70ed71378..b5491a593b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php @@ -111,7 +111,6 @@ class Create extends DocumentCreate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php index 1763491c19..bcd8682a48 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php @@ -70,7 +70,6 @@ class Delete extends DocumentDelete ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php index bb24e93de0..450fb4d746 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php @@ -58,7 +58,6 @@ class Get extends DocumentGet ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php index 86bfcfec85..27bd82195d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php @@ -51,7 +51,6 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php index 0879055a78..fe4ffc4995 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php @@ -69,7 +69,6 @@ class Update extends DocumentUpdate ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index 99e0487c93..0fbaa921cb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -72,7 +72,6 @@ class Upsert extends DocumentUpsert ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 230d391110..c51017fa75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -59,7 +59,6 @@ class XList extends DocumentXList ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php index 0d3bc9afc1..03316783cd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -62,7 +62,6 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php index b8be7edd56..0fb44ee94a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php @@ -52,7 +52,6 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index 5532203d0a..e0c590379b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -55,7 +55,6 @@ class XList extends CollectionXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php index e7e5f0132f..27454664f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php @@ -50,7 +50,6 @@ class Create extends TransactionsCreate ->inject('response') ->inject('dbForProject') ->inject('user') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php index 1228c83e30..4668ae2d15 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php @@ -54,7 +54,6 @@ class Create extends OperationsCreate ->inject('dbForProject') ->inject('transactionState') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php index 8be28ce9f7..4337a8d28d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php @@ -60,7 +60,6 @@ class Update extends TransactionsUpdate ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php index 87be8a9eab..89b9fbd8c2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php @@ -48,7 +48,6 @@ class Get extends DatabaseUsageGet ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php index 2cde337f5f..0bd96fc40a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php @@ -46,7 +46,6 @@ class XList extends DatabaseUsageXList ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index c5ae08728d..e7e34d4c5b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -17,7 +17,6 @@ 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\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -89,7 +88,6 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -107,8 +105,7 @@ class Create extends Action Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, - array $plan, - Authorization $authorization + array $plan ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index acfaa965ac..0aaea3bd4a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -78,7 +77,6 @@ class Create extends Base ->inject('project') ->inject('queueForBuilds') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -97,8 +95,7 @@ class Create extends Base Event $queueForEvents, Document $project, Build $queueForBuilds, - GitHub $github, - Authorization $authorization + GitHub $github ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -130,9 +127,7 @@ class Create extends Base queueForBuilds: $queueForBuilds, template: $template, github: $github, - activate: $activate, - referenceType: $type, - reference: $reference + activate: $activate ); $queueForEvents @@ -175,9 +170,6 @@ class Create extends Base ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); - - $this->updateEmptyManualRule($project, $function, $deployment, $dbForPlatform, $authorization); - $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php index 25dce63b38..69594c3d86 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -87,7 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github, + GitHub $github ) { $function = $dbForProject->getDocument('functions', $functionId); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 1a265298d3..81f55ba829 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -29,7 +29,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -100,7 +99,6 @@ class Create extends Base ->inject('proofForToken') ->inject('executor') ->inject('platform') - ->inject('authorization') ->callback($this->action(...)); } @@ -125,8 +123,7 @@ class Create extends Base Store $store, Token $proofForToken, Executor $executor, - array $platform, - Authorization $authorization, + array $platform ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -164,10 +161,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -183,7 +180,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); @@ -197,8 +194,10 @@ class Create extends Base throw new Exception(Exception::BUILD_NOT_READY); } - if (!$authorization->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization('execute'); + + if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); } $jwt = ''; // initialize @@ -296,7 +295,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -337,7 +336,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -489,7 +488,7 @@ class Create extends Base ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; - $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index c7a9a6d330..9a93e5a342 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -61,7 +61,6 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -71,8 +70,7 @@ class Delete extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -110,7 +108,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index c5eebe139e..6bd0a3675e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -52,7 +52,6 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -60,13 +59,12 @@ class Get extends Base string $functionId, string $executionId, Response $response, - Database $dbForProject, - Authorization $authorization + Database $dbForProject ) { - $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index ff381e1f3d..20680e87ff 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -60,7 +60,6 @@ class XList extends Base ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -69,13 +68,12 @@ class XList extends Base array $queries, bool $includeTotal, Response $response, - Database $dbForProject, - Authorization $authorization + Database $dbForProject ) { - $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index 6ad488283e..5c226c5925 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -115,7 +115,6 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -153,8 +152,7 @@ class Create extends Base Func $queueForFunctions, Database $dbForPlatform, Request $request, - GitHub $github, - Authorization $authorization + GitHub $github ) { // Temporary abuse check @@ -239,7 +237,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = $authorization->skip( + $schedule = Authorization::skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -317,7 +315,6 @@ class Create extends Base template: $template, github: $github, activate: true, - authorization: $authorization, reference: $providerBranch, referenceType: 'branch' ); @@ -369,7 +366,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $rule = $authorization->skip( + $rule = Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index 9cafc17bbe..dfa6636554 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -61,7 +61,6 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -71,8 +70,7 @@ class Delete extends Base Database $dbForProject, DeleteEvent $queueForDeletes, Event $queueForEvents, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -89,7 +87,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index aeccf98a02..b6dcfd6cf8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -62,7 +62,6 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -73,8 +72,7 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -103,7 +101,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -114,12 +112,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { + Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index 55c5b30418..adb29bc533 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -104,7 +104,6 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') - ->inject('authorization') ->callback($this->action(...)); } @@ -135,8 +134,7 @@ class Update extends Base Build $queueForBuilds, Database $dbForPlatform, GitHub $github, - Executor $executor, - Authorization $authorization + Executor $executor ) { // TODO: If only branch changes, re-deploy $function = $dbForProject->getDocument('functions', $functionId); @@ -284,7 +282,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents->setParam('functionId', $function->getId()); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index 1fa65d0cc9..acb6995d6f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -55,11 +55,10 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $functionId, string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $functionId, string $range, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); @@ -84,7 +83,7 @@ class Get extends Base str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index 38a95d4469..6a4ded4db7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -52,11 +52,10 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -76,7 +75,7 @@ class XList extends Base str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 5438479d40..815f1bd8fc 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -65,7 +65,6 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') - ->inject('authorization') ->callback($this->action(...)); } @@ -77,8 +76,7 @@ class Create extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Document $project, - Authorization $authorization + Document $project ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -121,7 +119,7 @@ class Create extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 161eed3112..50c1de4232 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -57,7 +57,6 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -66,8 +65,7 @@ class Delete extends Base string $variableId, Response $response, Database $dbForProject, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -94,7 +92,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 6af5ac90c2..5c1f5809cd 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -62,7 +62,6 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -74,8 +73,7 @@ class Update extends Base ?bool $secret, Response $response, Database $dbForProject, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -112,7 +110,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 8f041dd57b..414696306f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -25,6 +25,7 @@ use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Detector\Detection\Rendering\SSR; use Utopia\Detector\Detection\Rendering\XStatic; use Utopia\Detector\Detector\Rendering; @@ -1120,7 +1121,7 @@ class Builds extends Action ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $resource->getAttribute('schedule')) ->setAttribute('active', !empty($resource->getAttribute('schedule')) && !empty($resource->getAttribute('deploymentId'))); - $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } Console::info('Deployment action finished'); @@ -1349,6 +1350,7 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception + * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1437,11 +1439,11 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = $dbForPlatform->findOne('rules', [ + $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal("deploymentInternalId", [$deployment->getSequence()]), - ]); + ])); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $previewUrl = match($resource->getCollection()) { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 3de0322d6e..4ba51bca37 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -87,7 +87,6 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -107,8 +106,7 @@ class Create extends Action Device $deviceForSites, Device $deviceForLocal, Build $queueForBuilds, - array $plan, - Authorization $authorization + array $plan ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -278,7 +276,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -343,7 +341,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -368,8 +366,6 @@ class Create extends Action } } - - $metadata = null; $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 9554e2aa14..2f9b1bdfde 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -65,7 +65,6 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') - ->inject('authorization') ->callback($this->action(...)); } @@ -79,8 +78,7 @@ class Create extends Action Database $dbForPlatform, Event $queueForEvents, Build $queueForBuilds, - Device $deviceForSites, - Authorization $authorization + Device $deviceForSites ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -149,7 +147,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 30d5e779c1..5f1d446809 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -79,7 +79,6 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -98,8 +97,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github, - Authorization $authorization + GitHub $github ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -132,7 +130,6 @@ class Create extends Base template: $template, github: $github, activate: $activate, - authorization: $authorization, ); $queueForEvents @@ -192,7 +189,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -212,8 +209,6 @@ class Create extends Base ])) ); - $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); - $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index feff28427e..915e3c5c9f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -73,7 +72,6 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->inject('authorization') ->callback($this->action(...)); } @@ -89,8 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github, - Authorization $authorization + GitHub $github ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -113,7 +110,6 @@ class Create extends Base template: $template, github: $github, activate: $activate, - authorization: $authorization, reference: $reference, referenceType: $type ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index b5d956128b..f962d0118d 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -60,7 +60,6 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -71,8 +70,7 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { $site = $dbForProject->getDocument('sites', $siteId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -106,12 +104,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { + Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index 5c274d6a20..af96c10457 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -55,7 +55,6 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -63,8 +62,7 @@ class Get extends Base string $siteId, string $range, Response $response, - Database $dbForProject, - Authorization $authorization + Database $dbForProject ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -93,7 +91,7 @@ class Get extends Base ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index a90cb0cab9..d36cc56ae5 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -52,11 +52,10 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -79,7 +78,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index 4757461a98..ed5c23b6c1 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -22,7 +22,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -91,7 +90,6 @@ class Create extends Action ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->inject('authorization') ->callback($this->action(...)); } @@ -107,26 +105,26 @@ class Create extends Action Event $queueForEvents, string $mode, Device $deviceForFiles, - Device $deviceForLocal, - Authorization $authorization + Device $deviceForLocal ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $allowedPermissions = [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, + \Utopia\Database\Database::PERMISSION_READ, + \Utopia\Database\Database::PERMISSION_UPDATE, + \Utopia\Database\Database::PERMISSION_DELETE, ]; // Map aggregate permissions to into the set of individual permissions they represent. @@ -143,7 +141,7 @@ class Create extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!$isAPIKey && !$isPrivilegedUser) { foreach (\Utopia\Database\Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -156,7 +154,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -381,10 +379,11 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } // Trigger after create success hook @@ -428,12 +427,13 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } try { - $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index ca376842e2..eccacaafd2 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -14,7 +14,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -65,7 +64,6 @@ class Delete extends Action ->inject('queueForEvents') ->inject('deviceForFiles') ->inject('queueForDeletes') - ->inject('authorization') ->callback($this->action(...)); } @@ -77,33 +75,33 @@ class Delete extends Action Event $queueForEvents, Device $deviceForFiles, DeleteEvent $queueForDeletes, - Authorization $authorization ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); + $validator = new Authorization(Database::PERMISSION_DELETE); + $valid = $validator->isValid($bucket->getDelete()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for delete - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $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 && !$authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $deviceDeleted = false; @@ -127,7 +125,7 @@ class Delete extends Action if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = $authorization->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index bbceff51ec..45e3b83375 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -14,7 +14,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -69,7 +68,6 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->inject('authorization') ->callback($this->action(...)); } @@ -82,14 +80,13 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles, - Authorization $authorization, + Device $deviceForFiles ) { /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -97,16 +94,17 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index caaab29efc..77f163e5fb 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -10,7 +10,6 @@ use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -50,7 +49,6 @@ class Get extends Action ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } @@ -59,27 +57,27 @@ class Get extends Action string $fileId, Response $response, Database $dbForProject, - Authorization $authorization ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 7ab3e713bc..9c4e49d0bb 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -17,7 +17,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Image\Image; use Utopia\Platform\Action; @@ -91,7 +90,6 @@ class Get extends Action ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') - ->inject('authorization') ->callback($this->action(...)); } @@ -116,8 +114,7 @@ class Get extends Action Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, - Document $project, - Authorization $authorization + Document $project ) { if (!\extension_loaded('imagick')) { @@ -125,10 +122,10 @@ class Get extends Action } /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -140,16 +137,17 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -271,11 +269,11 @@ class Get extends Action $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!User::isPrivileged($authorization->getRoles())) { + if (!User::isPrivileged(Authorization::getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php index 516343e23f..67372435b1 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php @@ -51,7 +51,6 @@ class Get extends Action ->inject('project') ->inject('mode') ->inject('deviceForFiles') - ->inject('authorization') ->callback($this->action(...)); } @@ -65,8 +64,7 @@ class Get extends Action Database $dbForPlatform, Document $project, string $mode, - Device $deviceForFiles, - Authorization $authorization + Device $deviceForFiles ) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -88,15 +86,15 @@ class Get extends Action $disposition = $decoded['disposition'] ?? 'inline'; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index 57856c1564..be78cc358b 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -14,7 +14,6 @@ use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -63,7 +62,6 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } @@ -74,26 +72,26 @@ class Update extends Action ?array $permissions, Response $response, Database $dbForProject, - Event $queueForEvents, - Authorization $authorization + Event $queueForEvents ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $validator = new Authorization(Database::PERMISSION_UPDATE); + $valid = $validator->isValid($bucket->getUpdate()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for update - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -107,7 +105,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -120,7 +118,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$authorization->hasRole($role)) { + if (!Authorization::isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -141,7 +139,7 @@ class Update extends Action if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index 3874fedacf..41ee95b165 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -15,7 +15,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -70,7 +69,6 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->inject('authorization') ->callback($this->action(...)); } @@ -83,14 +81,13 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles, - Authorization $authorization + Device $deviceForFiles ) { /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -98,16 +95,17 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index 3663b56fab..e46fdb2a0a 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -16,7 +16,6 @@ use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -62,7 +61,6 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('mode') - ->inject('authorization') ->callback($this->action(...)); } @@ -73,22 +71,22 @@ class XList extends Action bool $includeTotal, Response $response, Database $dbForProject, - string $mode, - Authorization $authorization + string $mode ) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $validator = new Authorization(\Utopia\Database\Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } try { @@ -121,7 +119,7 @@ class XList extends Action if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -138,8 +136,8 @@ class XList extends Action $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; } else { - $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $includeTotal ? $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $includeTotal ? Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php index 4e75de27c8..5c3515122b 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php @@ -51,7 +51,6 @@ class Get extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') - ->inject('authorization') ->callback($this->action(...)); } @@ -60,8 +59,7 @@ class Get extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB, - Authorization $authorization, + callable $getLogsDB ): void { $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -77,20 +75,19 @@ class Get extends Action $statsDocId = md5('_inf_' . $metric); - $totalSize = 0; - - try { - $dbForLogs = $getLogsDB($project); - $storageStats = $authorization->skip(fn () => $dbForLogs->getDocument( + $dbForLogs = call_user_func($getLogsDB, $project); + $storageStats = Authorization::skip( + fn () => $dbForLogs->getDocument( 'stats', $statsDocId, [Query::select(['value'])] - )); + ) + ); - $totalSize = $storageStats->getAttribute('value', 0); - } catch (\Throwable) { - // Stats may not be available, default to 0 - } + /** + * The value can be 0 if stats were not aggregated when this request was made! + */ + $totalSize = $storageStats->isEmpty() ? 0 : $storageStats->getAttribute('value', 0); $bucket->setAttribute('totalSize', $totalSize); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php index 601d9b5321..a2c880ce08 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php @@ -58,7 +58,6 @@ class XList extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') - ->inject('authorization') ->callback($this->action(...)); } @@ -69,8 +68,7 @@ class XList extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB, - Authorization $authorization + callable $getLogsDB ) { try { $queries = Query::parseQueries($queries); @@ -119,6 +117,7 @@ class XList extends Action if (!empty($buckets)) { $bucketByStatsId = []; + $dbForLogs = call_user_func($getLogsDB, $project); foreach ($buckets as $bucket) { $metric = str_replace( @@ -135,28 +134,22 @@ class XList extends Action $bucket->setAttribute('totalSize', 0); } - try { - $dbForLogs = $getLogsDB($project); + /* @type Document[] $stats */ + $stats = Authorization::skip(function () use ($dbForLogs, $bucketByStatsId) { + $statsIds = array_keys($bucketByStatsId); - /* @var array $stats */ - $stats = $authorization->skip(function () use ($dbForLogs, $bucketByStatsId) { - $statsIds = array_keys($bucketByStatsId); + return $dbForLogs->find('stats', [ + Query::equal('$id', $statsIds), + Query::select(['value']), + ]); + }); - return $dbForLogs->find('stats', [ - Query::equal('$id', $statsIds), - Query::select(['value']), - ]); - }); + foreach ($stats as $stat) { + $bucket = $bucketByStatsId[$stat->getId()]; - foreach ($stats as $stat) { - $bucket = $bucketByStatsId[$stat->getId()]; - - if ($bucket) { - $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); - } + if ($bucket) { + $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); } - } catch (\Throwable) { - // Stats may not be available, default to 0 } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php index a7bda355da..b816e83f72 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php @@ -54,11 +54,10 @@ class Get extends Action ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, Authorization $authorization) + public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) { $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -76,7 +75,7 @@ class Get extends Action str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - $authorization->skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php index 44fdd54e8c..d29fa7c1b4 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php @@ -49,11 +49,10 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -64,7 +63,7 @@ class XList extends Action METRIC_FILES_STORAGE, ]; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index 5f1bd55788..f79dece530 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -6,31 +6,32 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Documents\User; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; class Action extends UtopiaAction { - protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, string $bucketId, string $fileId): array + protected function getFileAndBucket(Database $dbForProject, string $bucketId, string $fileId): array { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization(Database::PERMISSION_READ); + $valid = $validator->isValid($bucket->getRead()); + if (!$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 6cbaeaa915..3d1f6eef38 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -66,23 +65,23 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void + public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents): void { /** * @var Document $bucket * @var Document $file */ - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $validator = new Authorization(Database::PERMISSION_UPDATE); + $bucketPermission = $validator->isValid($bucket->getUpdate()); if ($fileSecurity) { - $filePermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); + $filePermission = $validator->isValid($file->getUpdate()); if (!$bucketPermission && !$filePermission) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 13da92cbc6..8a9301713b 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -13,7 +13,6 @@ use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; @@ -58,13 +57,12 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization) + public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index cc6981fa1b..3e35c1c1fa 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -31,7 +31,6 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') - ->inject('authorisation') ->callback($this->action(...)); } @@ -48,8 +47,8 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, - Authorization $authorization ): void { + Authorization::disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); @@ -67,14 +66,14 @@ class Migrate extends Action $count = 0; $total = $dbForPlatform->count('projects') + 1; - $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total, $authorization) { + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); $dbForProject->disableValidation(); try { $migration - ->setProject($project, $dbForProject, $dbForPlatform, $authorization, $getProjectDB) + ->setProject($project, $dbForProject, $dbForPlatform, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -89,7 +88,7 @@ class Migrate extends Action try { $migration - ->setProject($console, $getProjectDB($console), $dbForPlatform, $authorization, $getProjectDB) + ->setProject($console, $getProjectDB($console), $dbForPlatform, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 19ed3bc099..9698fe9034 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -8,6 +8,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; @@ -60,7 +61,7 @@ abstract class ScheduleBase extends Action $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $dbForPlatform->updateDocument('projects', $project->getId(), $project); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index 6d04d2109a..b64dd61f86 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -8,6 +8,7 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\System\System; /** @@ -60,7 +61,9 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue, $dbForPlatform) { + Console::loop(function () use ($queue) { + Authorization::disable(); + Authorization::setDefaultStatus(false); $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); /** diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 33ebd39092..5132687279 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -21,7 +21,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; -use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -59,7 +58,6 @@ class Certificates extends Action ->inject('log') ->inject('certificates') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -74,8 +72,6 @@ class Certificates extends Action * @param Certificate $queueForCertificates * @param Log $log * @param CertificatesAdapter $certificates - * @param array $plan - * @param ValidatorAuthorization $authorization * @return void * @throws Throwable * @throws \Utopia\Database\Exception @@ -91,8 +87,7 @@ class Certificates extends Action Certificate $queueForCertificates, Log $log, CertificatesAdapter $certificates, - array $plan, - ValidatorAuthorization $authorization, + array $plan ): void { $payload = $message->getPayload() ?? []; @@ -111,11 +106,11 @@ class Certificates extends Action switch ($action) { case Certificate::ACTION_DOMAIN_VERIFICATION: - $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $authorization, $validationDomain); + $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $validationDomain); break; case Certificate::ACTION_GENERATION: - $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); + $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $validationDomain); break; default: @@ -132,12 +127,10 @@ class Certificates extends Action * @param Realtime $queueForRealtime * @param Certificate $queueForCertificates * @param Log $log - * @param ValidatorAuthorization $authorization * @param string|null $validationDomain * @return void + * @throws Throwable * @throws \Utopia\Database\Exception - * @throws NotFound - * @throws \Utopia\Database\Exception\Query */ private function handleDomainVerificationAction( Domain $domain, @@ -148,13 +141,12 @@ class Certificates extends Action Realtime $queueForRealtime, Certificate $queueForCertificates, Log $log, - ValidatorAuthorization $authorization, ?string $validationDomain = null ): void { // Get rule $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ + ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); @@ -203,23 +195,15 @@ class Certificates extends Action * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents - * @param Webhook $queueForWebhooks * @param Func $queueForFunctions * @param Realtime $queueForRealtime - * @param Log $log * @param CertificatesAdapter $certificates - * @param ValidatorAuthorization $authorization * @param bool $skipRenewCheck * @param array $plan * @param string|null $validationDomain * @return void - * @throws Authorization - * @throws Conflict - * @throws NotFound - * @throws Structure * @throws Throwable * @throws \Utopia\Database\Exception - * @throws \Utopia\Database\Exception\Query */ private function handleCertificateGenerationAction( Domain $domain, @@ -232,7 +216,6 @@ class Certificates extends Action Realtime $queueForRealtime, Log $log, CertificatesAdapter $certificates, - ValidatorAuthorization $authorization, bool $skipRenewCheck = false, array $plan = [], ?string $validationDomain = null @@ -269,8 +252,8 @@ class Certificates extends Action // Get rule document for domain // TODO: (@Meldiron) Remove after 1.7.x migration $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ + ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 9687f4f4bb..0b2f7c75ae 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -19,10 +19,12 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; +use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -201,6 +203,7 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void + * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -999,14 +1002,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); + $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); if ($bucket->isEmpty()) { Console::error('Failed to get bucket for deployment screenshots'); return; } foreach ($screenshotIds as $id) { - $file = $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id); + $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index d047d0925e..4a564011b2 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -15,6 +15,7 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; @@ -336,6 +337,7 @@ class Functions extends Action * @param string|null $eventData * @param string|null $executionId * @return void + * @throws Authorization * @throws Structure * @throws \Utopia\Database\Exception * @throws Conflict diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 6ef2f1899c..e1039510f4 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -80,7 +80,6 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -98,7 +97,6 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, - Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -136,13 +134,7 @@ class Migrations extends Action } try { - $this->processMigration( - $migration, - $queueForRealtime, - $queueForMails, - $platform, - $authorization - ); + $this->processMigration($migration, $queueForRealtime, $queueForMails, $platform); } finally { $this->dbForProject = null; $this->dbForPlatform = null; @@ -153,7 +145,7 @@ class Migrations extends Action $this->plan = []; $this->sourceReport = []; - \gc_collect_cycles(); + gc_collect_cycles(); } } @@ -327,7 +319,6 @@ class Migrations extends Action Realtime $queueForRealtime, Mail $queueForMails, array $platform, - Authorization $authorization, ): void { $project = $this->project; @@ -444,14 +435,14 @@ class Migrations extends Action $destination?->success(); $source?->success(); - // TODO: Move to CSV hook + // todo: Move to CSV hook if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform); } } } finally { - $source?->cleanup(); - $destination?->cleanup(); + $source?->cleanUp(); + $destination?->cleanUp(); $transfer = null; $source = null; @@ -466,10 +457,11 @@ class Migrations extends Action * @param Document $project * @param Document $migration * @param Mail $queueForMails - * @param Realtime $queueForRealtime - * @param array $platform - * @param Authorization $authorization * @return void + * @throws AuthorizationException + * @throws Structure + * @throws \Utopia\Database\Exception + * @throws Exception */ protected function handleCSVExportComplete( Document $project, @@ -477,7 +469,6 @@ class Migrations extends Action Mail $queueForMails, Realtime $queueForRealtime, array $platform, - Authorization $authorization, ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -491,7 +482,7 @@ class Migrations extends Action throw new \Exception('User ' . $userInternalId . ' not found'); } - $bucket = $authorization->skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new \Exception('Bucket not found'); } diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index cbd22aaee5..a85b0a897c 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -7,6 +7,7 @@ use Utopia\Auth\Proofs\Token; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; class User extends Document @@ -35,11 +36,11 @@ class User extends Document * * @return array */ - public function getRoles($authorization): array + public function getRoles(): array { $roles = []; - if (!$this->isPrivileged($authorization->getRoles()) && !$this->isApp($authorization->getRoles())) { + if (!$this->isPrivileged(Authorization::getRoles()) && !$this->isApp(Authorization::getRoles())) { if ($this->getId()) { $roles[] = Role::user($this->getId())->toString(); $roles[] = Role::users()->toString(); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index c87279f126..cb449e6ffa 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -214,7 +214,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = $this->authorization->getRoles(); + $roles = Authorization::getRoles(); $isAppUser = User::isApp($roles); if ($isAppUser) { @@ -237,11 +237,4 @@ class Request extends UtopiaRequest ksort($params); return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } - - private ?Authorization $authorization = null; - - public function setAuthorization(Authorization $authorization): void - { - $this->authorization = $authorization; - } } diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 6d47d4d150..56fed746d9 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -10,7 +10,7 @@ abstract class Filter private array $params; private ?Database $dbForProject; - public function __construct(?Database $dbForProject = null, array $params = []) + public function __construct(Database $dbForProject = null, array $params = []) { $this->params = $params; $this->dbForProject = $dbForProject; diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index e3d5fe2f79..69e7da6b7a 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -7,6 +7,7 @@ use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; class V20 extends Filter { @@ -137,7 +138,7 @@ class V20 extends Filter } try { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $database = Authorization::skip(fn () => $dbForProject->getDocument( 'databases', $databaseId )); @@ -149,7 +150,7 @@ class V20 extends Filter } try { - $collection = $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $collection = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId )); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index f2ac486f82..1dfaa1a41f 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -483,7 +483,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = $this->authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = DBUser::isPrivileged($roles); $isAppUser = DBUser::isApp($roles); @@ -651,11 +651,4 @@ class Response extends SwooleResponse self::$showSensitive = false; } } - - private ?Authorization $authorization = null; - - public function setAuthorization(Authorization $authorization): void - { - $this->authorization = $authorization; - } } diff --git a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index 0c9854160e..6496aa285a 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,19 +17,6 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - - return $this->authorization; - } - public function createCollection(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ @@ -124,8 +111,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -147,7 +134,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } @@ -158,8 +145,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -235,7 +222,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index 84cb4bce3a..2f69c037d0 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -17,19 +17,6 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - return $this->authorization; - } - - public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ @@ -124,8 +111,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicRows = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -147,7 +134,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } @@ -158,8 +145,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; - $roles = $this->getAuthorization()->getRoles(); - $this->getAuthorization()->cleanRoles(); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -235,7 +222,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateRow['headers']['status-code']); foreach ($roles as $role) { - $this->getAuthorization()->addRole($role); + Authorization::setRole($role); } } diff --git a/tests/e2e/Services/Tokens/TokensBase.php b/tests/e2e/Services/Tokens/TokensBase.php index ca6feed5fa..a4461c06c2 100644 --- a/tests/e2e/Services/Tokens/TokensBase.php +++ b/tests/e2e/Services/Tokens/TokensBase.php @@ -94,7 +94,7 @@ trait TokensBase $this->assertEquals(401, $failedPreview['body']['code']); $this->assertEquals(401, $failedPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedPreview['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedPreview['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedPreview['body']['message']); // Extended file preview. Should fail as an anonymous user with no form of any access to the file. $failedCustomPreview = $this->client->call( @@ -113,7 +113,7 @@ trait TokensBase $this->assertEquals(401, $failedCustomPreview['body']['code']); $this->assertEquals(401, $failedCustomPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedCustomPreview['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedCustomPreview['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedCustomPreview['body']['message']); // File view. Should fail as an anonymous user with no form of any access to the file. $failedView = $this->client->call( @@ -124,7 +124,7 @@ trait TokensBase $this->assertEquals(401, $failedView['body']['code']); $this->assertEquals(401, $failedView['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedView['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedView['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedView['body']['message']); // File download. Should fail as an anonymous user with no form of any access to the file. $failedDownload = $this->client->call( @@ -135,7 +135,7 @@ trait TokensBase $this->assertEquals(401, $failedDownload['body']['code']); $this->assertEquals(401, $failedDownload['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedDownload['body']['type']); - $this->assertEquals('No permissions provided for action \'read\'', $failedDownload['body']['message']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $failedDownload['body']['message']); return $data; } diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 7df5b8d1e6..42e433568f 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -7,7 +7,6 @@ use Appwrite\Utopia\Database\Documents\User; use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -34,19 +33,6 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; - - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - return $this->authorization; - } - public function setUp(): void { /** @@ -79,7 +65,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -103,7 +89,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); diff --git a/tests/unit/Utopia/Database/Documents/UserTest.php b/tests/unit/Utopia/Database/Documents/UserTest.php index d5706e7bec..4675e8d73f 100644 --- a/tests/unit/Utopia/Database/Documents/UserTest.php +++ b/tests/unit/Utopia/Database/Documents/UserTest.php @@ -14,25 +14,13 @@ use Utopia\Database\Validator\Roles; class UserTest extends TestCase { - private $authorization; - - public function getAuthorization(): Authorization - { - if (isset($this->authorization)) { - return $this->authorization; - } - - $this->authorization = new Authorization(); - return $this->authorization; - } - /** * Reset Roles */ public function tearDown(): void { - $this->getAuthorization()->cleanRoles(); - $this->getAuthorization()->addRole(Role::any()->toString()); + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); } public function testSessionVerify(): void @@ -209,7 +197,7 @@ class UserTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -245,7 +233,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -266,21 +254,21 @@ class UserTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles); // Enable single verification type $user['emailVerification'] = true; - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); } public function testPrivilegedUserRoles(): void { - $this->getAuthorization()->addRole(User::ROLE_OWNER); + Authorization::setRole(User::ROLE_OWNER); $user = new User([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -305,7 +293,8 @@ class UserTest extends TestCase ] ] ]); - $roles = $user->getRoles($this->getAuthorization()); + + $roles = $user->getRoles(); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -323,7 +312,7 @@ class UserTest extends TestCase public function testAppUserRoles(): void { - $this->getAuthorization()->addRole(User::ROLE_APPS); + Authorization::setRole(User::ROLE_APPS); $user = new User([ '$id' => ID::custom('123'), 'memberships' => [ @@ -347,7 +336,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles($this->getAuthorization()); + $roles = $user->getRoles(); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); From 2cfb5ecfd9ba5770d69c0ec900e157504a92227a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 04:08:00 +1300 Subject: [PATCH 40/52] Reapply "Merge pull request #11130 from appwrite/feat-auth-instance" This reverts commit 38687bc24e63b5fcbeec6118521c43a863753769. --- app/cli.php | 28 ++- app/config/storage/resource_limits.php | 4 +- app/controllers/api/account.php | 146 ++++++++------ app/controllers/api/graphql.php | 5 +- app/controllers/api/health.php | 18 +- app/controllers/api/messaging.php | 65 +++--- app/controllers/api/migrations.php | 14 +- app/controllers/api/project.php | 9 +- app/controllers/api/teams.php | 63 +++--- app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 60 +++--- app/controllers/general.php | 189 +++++++++--------- app/controllers/shared/api.php | 53 ++--- app/controllers/shared/api/auth.php | 7 +- app/http.php | 28 ++- app/init/database/filters.php | 47 +++-- app/init/resources.php | 106 +++++----- app/realtime.php | 41 +++- app/worker.php | 53 +++-- composer.json | 10 +- composer.lock | 105 +++++----- src/Appwrite/Databases/TransactionState.php | 10 +- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Avatars/Http/Action.php | 10 +- .../Modules/Avatars/Http/Browsers/Get.php | 2 +- .../Avatars/Http/Cards/Cloud/Back/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/Front/Get.php | 7 +- .../Avatars/Http/Cards/Cloud/OG/Get.php | 7 +- .../Modules/Avatars/Http/CreditCards/Get.php | 2 +- .../Modules/Avatars/Http/Flags/Get.php | 2 +- .../Platform/Modules/Compute/Base.php | 41 +++- .../Modules/Console/Http/Resources/Get.php | 6 +- .../Collections/Attributes/Action.php | 10 +- .../Collections/Attributes/Boolean/Create.php | 6 +- .../Collections/Attributes/Boolean/Update.php | 5 +- .../Attributes/Datetime/Create.php | 7 +- .../Attributes/Datetime/Update.php | 5 +- .../Collections/Attributes/Delete.php | 5 +- .../Collections/Attributes/Email/Create.php | 7 +- .../Collections/Attributes/Email/Update.php | 5 +- .../Collections/Attributes/Enum/Create.php | 7 +- .../Collections/Attributes/Enum/Update.php | 5 +- .../Collections/Attributes/Float/Create.php | 6 +- .../Collections/Attributes/Float/Update.php | 5 +- .../Databases/Collections/Attributes/Get.php | 5 +- .../Collections/Attributes/IP/Create.php | 7 +- .../Collections/Attributes/IP/Update.php | 5 +- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Integer/Update.php | 5 +- .../Collections/Attributes/Line/Create.php | 6 +- .../Collections/Attributes/Line/Update.php | 5 +- .../Collections/Attributes/Point/Create.php | 6 +- .../Collections/Attributes/Point/Update.php | 5 +- .../Collections/Attributes/Polygon/Create.php | 6 +- .../Collections/Attributes/Polygon/Update.php | 5 +- .../Attributes/Relationship/Create.php | 7 +- .../Attributes/Relationship/Update.php | 6 +- .../Collections/Attributes/String/Create.php | 8 +- .../Collections/Attributes/String/Update.php | 6 +- .../Collections/Attributes/URL/Create.php | 7 +- .../Collections/Attributes/URL/Update.php | 6 +- .../Collections/Attributes/XList.php | 5 +- .../Http/Databases/Collections/Create.php | 5 +- .../Http/Databases/Collections/Delete.php | 5 +- .../Collections/Documents/Action.php | 7 +- .../Documents/Attribute/Decrement.php | 13 +- .../Documents/Attribute/Increment.php | 13 +- .../Collections/Documents/Create.php | 43 ++-- .../Collections/Documents/Delete.php | 17 +- .../Databases/Collections/Documents/Get.php | 12 +- .../Collections/Documents/Logs/XList.php | 5 +- .../Collections/Documents/Update.php | 26 +-- .../Collections/Documents/Upsert.php | 26 +-- .../Databases/Collections/Documents/XList.php | 16 +- .../Http/Databases/Collections/Get.php | 5 +- .../Databases/Collections/Indexes/Create.php | 5 +- .../Databases/Collections/Indexes/Delete.php | 5 +- .../Databases/Collections/Indexes/Get.php | 5 +- .../Databases/Collections/Indexes/XList.php | 7 +- .../Http/Databases/Collections/Logs/XList.php | 39 ++-- .../Http/Databases/Collections/Update.php | 5 +- .../Http/Databases/Collections/Usage/Get.php | 5 +- .../Http/Databases/Collections/XList.php | 5 +- .../Http/Databases/Transactions/Create.php | 5 +- .../Transactions/Operations/Create.php | 34 ++-- .../Http/Databases/Transactions/Update.php | 37 ++-- .../Databases/Http/Databases/Usage/Get.php | 5 +- .../Databases/Http/Databases/Usage/XList.php | 5 +- .../Tables/Columns/Boolean/Create.php | 1 + .../Tables/Columns/Boolean/Update.php | 1 + .../Tables/Columns/Datetime/Create.php | 1 + .../Tables/Columns/Datetime/Update.php | 1 + .../Http/TablesDB/Tables/Columns/Delete.php | 1 + .../TablesDB/Tables/Columns/Email/Create.php | 1 + .../TablesDB/Tables/Columns/Email/Update.php | 1 + .../TablesDB/Tables/Columns/Enum/Create.php | 1 + .../TablesDB/Tables/Columns/Enum/Update.php | 1 + .../TablesDB/Tables/Columns/Float/Create.php | 1 + .../TablesDB/Tables/Columns/Float/Update.php | 1 + .../Http/TablesDB/Tables/Columns/Get.php | 1 + .../TablesDB/Tables/Columns/IP/Create.php | 1 + .../TablesDB/Tables/Columns/IP/Update.php | 1 + .../Tables/Columns/Integer/Create.php | 1 + .../Tables/Columns/Integer/Update.php | 1 + .../TablesDB/Tables/Columns/Line/Create.php | 1 + .../TablesDB/Tables/Columns/Line/Update.php | 1 + .../TablesDB/Tables/Columns/Point/Create.php | 1 + .../TablesDB/Tables/Columns/Point/Update.php | 1 + .../Tables/Columns/Polygon/Create.php | 1 + .../Tables/Columns/Polygon/Update.php | 1 + .../Tables/Columns/Relationship/Create.php | 1 + .../Tables/Columns/Relationship/Update.php | 1 + .../TablesDB/Tables/Columns/String/Create.php | 1 + .../TablesDB/Tables/Columns/String/Update.php | 1 + .../TablesDB/Tables/Columns/URL/Create.php | 1 + .../TablesDB/Tables/Columns/URL/Update.php | 1 + .../Http/TablesDB/Tables/Columns/XList.php | 1 + .../Databases/Http/TablesDB/Tables/Create.php | 1 + .../Databases/Http/TablesDB/Tables/Delete.php | 1 + .../Databases/Http/TablesDB/Tables/Get.php | 1 + .../Http/TablesDB/Tables/Indexes/Create.php | 2 + .../Http/TablesDB/Tables/Indexes/Delete.php | 1 + .../Http/TablesDB/Tables/Indexes/Get.php | 1 + .../Http/TablesDB/Tables/Indexes/XList.php | 1 + .../Http/TablesDB/Tables/Logs/XList.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Delete.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Update.php | 1 + .../Http/TablesDB/Tables/Rows/Bulk/Upsert.php | 1 + .../TablesDB/Tables/Rows/Column/Decrement.php | 1 + .../TablesDB/Tables/Rows/Column/Increment.php | 1 + .../Http/TablesDB/Tables/Rows/Create.php | 1 + .../Http/TablesDB/Tables/Rows/Delete.php | 1 + .../Http/TablesDB/Tables/Rows/Get.php | 1 + .../Http/TablesDB/Tables/Rows/Logs/XList.php | 1 + .../Http/TablesDB/Tables/Rows/Update.php | 1 + .../Http/TablesDB/Tables/Rows/Upsert.php | 1 + .../Http/TablesDB/Tables/Rows/XList.php | 1 + .../Databases/Http/TablesDB/Tables/Update.php | 1 + .../Http/TablesDB/Tables/Usage/Get.php | 1 + .../Databases/Http/TablesDB/Tables/XList.php | 1 + .../Http/TablesDB/Transactions/Create.php | 1 + .../Transactions/Operations/Create.php | 1 + .../Http/TablesDB/Transactions/Update.php | 1 + .../Databases/Http/TablesDB/Usage/Get.php | 1 + .../Databases/Http/TablesDB/Usage/XList.php | 1 + .../Functions/Http/Deployments/Create.php | 5 +- .../Http/Deployments/Template/Create.php | 12 +- .../Functions/Http/Deployments/Vcs/Create.php | 2 +- .../Functions/Http/Executions/Create.php | 25 +-- .../Functions/Http/Executions/Delete.php | 6 +- .../Modules/Functions/Http/Executions/Get.php | 10 +- .../Functions/Http/Executions/XList.php | 10 +- .../Functions/Http/Functions/Create.php | 9 +- .../Functions/Http/Functions/Delete.php | 6 +- .../Http/Functions/Deployment/Update.php | 10 +- .../Functions/Http/Functions/Update.php | 6 +- .../Modules/Functions/Http/Usage/Get.php | 5 +- .../Modules/Functions/Http/Usage/XList.php | 5 +- .../Functions/Http/Variables/Create.php | 6 +- .../Functions/Http/Variables/Delete.php | 6 +- .../Functions/Http/Variables/Update.php | 6 +- .../Modules/Functions/Workers/Builds.php | 8 +- .../Modules/Sites/Http/Deployments/Create.php | 10 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Template/Create.php | 9 +- .../Sites/Http/Deployments/Vcs/Create.php | 6 +- .../Sites/Http/Sites/Deployment/Update.php | 8 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 6 +- .../Modules/Sites/Http/Usage/XList.php | 5 +- .../Storage/Http/Buckets/Files/Create.php | 36 ++-- .../Storage/Http/Buckets/Files/Delete.php | 22 +- .../Http/Buckets/Files/Download/Get.php | 18 +- .../Storage/Http/Buckets/Files/Get.php | 16 +- .../Http/Buckets/Files/Preview/Get.php | 22 +- .../Storage/Http/Buckets/Files/Push/Get.php | 12 +- .../Storage/Http/Buckets/Files/Update.php | 24 ++- .../Storage/Http/Buckets/Files/View/Get.php | 18 +- .../Storage/Http/Buckets/Files/XList.php | 22 +- .../Modules/Storage/Http/Buckets/Get.php | 23 ++- .../Modules/Storage/Http/Buckets/XList.php | 35 ++-- .../Modules/Storage/Http/Usage/Get.php | 5 +- .../Modules/Storage/Http/Usage/XList.php | 5 +- .../Http/Tokens/Buckets/Files/Action.php | 17 +- .../Http/Tokens/Buckets/Files/Create.php | 11 +- .../Http/Tokens/Buckets/Files/XList.php | 6 +- src/Appwrite/Platform/Tasks/Migrate.php | 9 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 3 +- .../Platform/Tasks/StatsResources.php | 5 +- .../Platform/Workers/Certificates.php | 33 ++- src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Platform/Workers/Functions.php | 2 - src/Appwrite/Platform/Workers/Migrations.php | 31 ++- .../Utopia/Database/Documents/User.php | 5 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 5 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 25 ++- .../DatabasesPermissionsGuestTest.php | 25 ++- tests/e2e/Services/Tokens/TokensBase.php | 8 +- .../unit/Messaging/MessagingChannelsTest.php | 18 +- .../Utopia/Database/Documents/UserTest.php | 33 ++- 202 files changed, 1479 insertions(+), 978 deletions(-) diff --git a/app/cli.php b/app/cli.php index 07966b2450..7493d10ab3 100644 --- a/app/cli.php +++ b/app/cli.php @@ -41,8 +41,6 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false)); // require controllers after overwriting runtimes require_once __DIR__ . '/controllers/general.php'; -Authorization::disable(); - CLI::setResource('register', fn () => $register); CLI::setResource('cache', function ($pools) { @@ -60,7 +58,13 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('dbForPlatform', function ($pools, $cache) { +CLI::setResource('authorization', function () { + $authorization = new Authorization(); + $authorization->disable(); + return $authorization; +}, []); + +CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -74,6 +78,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -99,7 +104,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { } return $dbForPlatform; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('console', function () { return new Document(Config::getParam('console')); @@ -110,10 +115,10 @@ CLI::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -146,6 +151,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); + $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -162,17 +168,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { +CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -182,6 +189,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) @@ -194,7 +202,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); diff --git a/app/config/storage/resource_limits.php b/app/config/storage/resource_limits.php index cfbcea5a47..43ed2b8b05 100644 --- a/app/config/storage/resource_limits.php +++ b/app/config/storage/resource_limits.php @@ -3,4 +3,6 @@ use Utopia\Image\Image; use Utopia\System\System; -Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); +if (\class_exists('Imagick')) { + Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64))); +} diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 2c481b500c..bcea3387a2 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -207,10 +207,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr } -$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $userFromRequest */ - $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -266,7 +266,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -275,7 +275,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + $authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -376,8 +376,9 @@ App::post('/v1/account') ->inject('user') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('hooks') - ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Hooks $hooks) { + ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Hooks $hooks) { $email = \strtolower($email); if ('console' === $project->getId()) { @@ -469,9 +470,9 @@ App::post('/v1/account') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -497,9 +498,9 @@ App::post('/v1/account') throw new Exception(Exception::USER_ALREADY_EXISTS); } - Authorization::unsetRole(Role::guests()->toString()); - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $authorization->removeRole(Role::guests()->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::users()->toString()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -976,7 +977,8 @@ App::post('/v1/account/sessions/email') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -1021,7 +1023,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) { @@ -1120,7 +1122,8 @@ App::post('/v1/account/sessions/anonymous') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1165,7 +1168,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; @@ -1191,7 +1194,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -1274,6 +1277,7 @@ App::post('/v1/account/sessions/token') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') +->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1470,7 +1474,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('store') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) { + ->inject('authorization') + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1726,7 +1731,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ]); $user->removeAttribute('$sequence'); - $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $userDoc = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), @@ -1744,8 +1749,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::users()->toString()); if (false === $user->getAttribute('status')) { // Account is blocked $failureRedirect(Exception::USER_BLOCKED); // User is in status blocked @@ -1816,7 +1821,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1840,7 +1845,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2077,7 +2082,8 @@ App::post('/v1/account/tokens/magic-url') ->inject('queueForMails') ->inject('proofForPassword') ->inject('platform') - ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform) { + ->inject('authorization') + ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2150,7 +2156,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); } $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); @@ -2170,7 +2176,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2356,7 +2362,8 @@ App::post('/v1/account/tokens/email') ->inject('queueForMails') ->inject('proofForPassword') ->inject('proofForCode') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2425,9 +2432,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2465,7 +2472,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2662,10 +2669,11 @@ App::put('/v1/account/sessions/magic-url') ->inject('queueForMails') ->inject('store') ->inject('proofForCode') - ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) { + ->inject('authorization') + ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode, $authorization) use ($createSession) { $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); $proofForToken->setHash(new Sha()); - $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode); + $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode, $authorization); }); App::put('/v1/account/sessions/phone') @@ -2711,6 +2719,7 @@ App::put('/v1/account/sessions/phone') ->inject('store') ->inject('proofForToken') ->inject('proofForCode') + ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2754,7 +2763,8 @@ App::post('/v1/account/tokens/phone') ->inject('plan') ->inject('store') ->inject('proofForCode') - ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2804,9 +2814,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2852,7 +2862,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3243,7 +3253,8 @@ App::patch('/v1/account/email') ->inject('project') ->inject('hooks') ->inject('proofForPassword') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->inject('authorization') + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3295,7 +3306,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3311,7 +3322,7 @@ App::patch('/v1/account/email') $oldTarget = $user->find('identifier', $oldEmail, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); + $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate) { @@ -3352,8 +3363,9 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') - ->action(function (string $phone, string $password, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->inject('proofForPassword') +->inject('authorization') + ->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3368,7 +3380,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3399,7 +3411,7 @@ App::patch('/v1/account/phone') $oldTarget = $user->find('identifier', $oldPhone, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); + $authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate $th) { @@ -3535,7 +3547,9 @@ App::post('/v1/account/recovery') ->inject('queueForMails') ->inject('queueForEvents') ->inject('proofForToken') - ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { + if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } @@ -3571,7 +3585,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3727,7 +3741,8 @@ App::put('/v1/account/recovery') ->inject('hooks') ->inject('proofForPassword') ->inject('proofForToken') - ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { +->inject('authorization') + ->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ $profile = $dbForProject->getDocument('users', $userId); @@ -3741,7 +3756,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $newPassword = $proofForPassword->hash($password); @@ -3844,7 +3859,8 @@ App::post('/v1/account/verifications/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('proofForToken') - ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3873,7 +3889,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4072,9 +4088,10 @@ App::put('/v1/account/verifications/email') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForToken') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4086,7 +4103,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -4146,7 +4163,8 @@ App::post('/v1/account/verifications/phone') ->inject('queueForStatsUsage') ->inject('plan') ->inject('proofForCode') - ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -4185,7 +4203,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4291,9 +4309,10 @@ App::put('/v1/account/verifications/phone') ->inject('dbForProject') ->inject('queueForEvents') ->inject('proofForCode') - ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode, Authorization $authorization) { /** @var Appwrite\Utopia\Database\Documents\User $profile */ - $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); @@ -4305,7 +4324,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -4358,12 +4377,13 @@ App::post('/v1/account/targets/push') ->inject('dbForProject') ->inject('store') ->inject('proofForToken') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken, Authorization $authorization) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); @@ -4438,9 +4458,10 @@ App::put('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); @@ -4503,8 +4524,9 @@ App::delete('/v1/account/targets/:targetId/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + ->inject('authorization') + ->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index baf0ba1512..e0cc4181db 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -28,11 +28,12 @@ use Utopia\Validator\Text; App::init() ->groups(['graphql']) ->inject('project') - ->action(function (Document $project) { + ->inject('authorization') + ->action(function (Document $project, Authorization $authorization) { if ( array_key_exists('graphql', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['graphql'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 907ed54de8..d6388185d3 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -27,6 +27,7 @@ use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Config\Config; use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; use Utopia\Registry\Registry; @@ -101,7 +102,8 @@ App::get('/v1/health/db') )) ->inject('response') ->inject('pools') - ->action(function (Response $response, Group $pools) { + ->inject('authorization') + ->action(action: function (Response $response, Group $pools, Authorization $authorization) { $output = []; $failures = []; @@ -114,14 +116,14 @@ App::get('/v1/health/db') foreach ($config as $database) { try { $adapter = new DatabasePool($pools->get($database)); - + $adapter->setAuthorization($authorization); $checkStart = \microtime(true); if ($adapter->ping()) { $output[] = new Document([ 'name' => $key . " ($database)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $database; @@ -132,6 +134,8 @@ App::get('/v1/health/db') } } + // Only throw error if ALL databases failed (no successful pings) + // This allows partial failures in environments where not all DBs are ready if (!empty($failures)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); } @@ -181,7 +185,7 @@ App::get('/v1/health/cache') $output[] = new Document([ 'name' => $key . " ($cache)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $cache; @@ -241,7 +245,7 @@ App::get('/v1/health/pubsub') $output[] = new Document([ 'name' => $key . " ($pubsub)", 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]); } else { $failures[] = $pubsub; @@ -823,7 +827,7 @@ App::get('/v1/health/storage/local') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); @@ -875,7 +879,7 @@ App::get('/v1/health/storage') $output = [ 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) + 'ping' => \round((\microtime(true) - $checkStart) * 1000) ]; $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 0b6a314dc5..6ac36fe3c0 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -36,6 +36,7 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -1073,8 +1074,9 @@ App::get('/v1/messaging/providers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1100,7 +1102,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found."); @@ -2481,8 +2483,9 @@ App::get('/v1/messaging/topics') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2508,7 +2511,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Topic '{$topicId}' for the 'cursor' value not found."); @@ -2782,29 +2785,27 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) { + ->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { $subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId; - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); } - - $validator = new Authorization('subscribe'); - - if (!$validator->isValid($topic->getAttribute('subscribe'))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2837,7 +2838,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2882,8 +2883,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2894,7 +2896,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2917,7 +2919,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Subscriber '{$subscriberId}' for the 'cursor' value not found."); @@ -2931,10 +2933,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) { - return function () use ($subscriber, $dbForProject) { - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $authorization) { + return function () use ($subscriber, $dbForProject, $authorization) { + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); return $subscriber ->setAttribute('target', $target) @@ -3067,9 +3069,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Authorization $authorization, Response $response) { + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3081,8 +3084,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') throw new Exception(Exception::SUBSCRIBER_NOT_FOUND); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber ->setAttribute('target', $target) @@ -3118,9 +3121,10 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) { + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -3143,7 +3147,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3702,8 +3706,9 @@ App::get('/v1/messaging/messages') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3729,7 +3734,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('messages', $messageId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found."); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 3989ad3298..1a17853577 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -342,6 +342,7 @@ App::post('/v1/migrations/csv/imports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('platform') ->inject('deviceForFiles') @@ -356,6 +357,7 @@ App::post('/v1/migrations/csv/imports') Response $response, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, Document $project, array $platform, Device $deviceForFiles, @@ -363,7 +365,7 @@ App::post('/v1/migrations/csv/imports') Event $queueForEvents, Migration $queueForMigrations ) { - $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -374,7 +376,7 @@ App::post('/v1/migrations/csv/imports') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } @@ -491,6 +493,7 @@ App::post('/v1/migrations/csv/exports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('platform') ->inject('queueForEvents') @@ -509,6 +512,7 @@ App::post('/v1/migrations/csv/exports') Response $response, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, Document $project, array $platform, Event $queueForEvents, @@ -520,7 +524,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); + $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'default')); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -533,12 +537,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $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 = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index a57675d3e8..cda03f923a 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -45,9 +45,10 @@ App::get('/v1/project/usage') ->inject('response') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('getLogsDB') ->inject('smsRates') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) { + ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, Authorization $authorization, callable $getLogsDB, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -102,7 +103,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { + $authorization->skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; @@ -286,7 +287,7 @@ App::get('/v1/project/usage') }, $dbForProject->find('functions')); // This total is includes free and paid SMS usage - $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ + $authPhoneTotal = $authorization->skip(fn () => $dbForProject->sum('stats', 'value', [ Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), @@ -294,7 +295,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ + $authPhoneMetrics = $authorization->skip(fn () => $dbForProject->find('stats', [ Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 1f8555b6cd..aa67a90885 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -86,16 +86,17 @@ App::post('/v1/teams') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($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)), @@ -491,6 +492,7 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -500,9 +502,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('plan') ->inject('proofForPassword') ->inject('proofForToken') - ->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 $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { - $isAppUser = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) { + $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -619,13 +621,13 @@ App::post('/v1/teams/:teamId/memberships') ]); try { - $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument)); + $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', $userDocument)); } catch (Duplicate $th) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); 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'); @@ -661,11 +663,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { $membership->setAttribute('secret', $proofForToken->hash($secret)); @@ -677,7 +679,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + $authorization->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } else { throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); @@ -863,7 +865,8 @@ App::get('/v1/teams/:teamId/memberships') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -933,7 +936,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1004,7 +1007,8 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); @@ -1024,7 +1028,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -1103,8 +1107,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->inject('user') ->inject('project') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -1121,9 +1126,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($authorization->getRoles()); + $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { // Quick check: fetch up to 2 owners to determine if only one exists @@ -1204,12 +1209,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') ->inject('store') ->inject('proofForToken') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1218,7 +1224,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::MEMBERSHIP_NOT_FOUND); } - $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); @@ -1254,11 +1260,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->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))); // Create session for the user if not logged in if (!$hasSession) { - Authorization::setRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1286,7 +1292,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - Authorization::setRole(Role::user($userId)->toString()); + $authorization->addRole(Role::user($userId)->toString()); $encoded = $store ->setProperty('id', $user->getId()) @@ -1324,7 +1330,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1368,8 +1374,9 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->inject('project') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1427,7 +1434,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); } $queueForEvents diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bbe1d8a84a..a963284538 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2678,8 +2678,8 @@ App::get('/v1/users/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('register') - ->action(function (string $range, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -2689,7 +2689,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 4249dbfd48..2270f4fd89 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -76,7 +76,7 @@ use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, array $platform) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Authorization $authorization, Build $queueForBuilds, callable $getProjectDB, Request $request, array $platform) { $errors = []; foreach ($repositories as $repository) { try { @@ -87,12 +87,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); - $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -141,7 +141,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -180,7 +180,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } else { @@ -191,7 +191,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ + $latestComment = $authorization->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -212,7 +212,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -251,7 +251,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -294,7 +294,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -334,7 +334,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); - Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); + $authorization->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); @@ -344,7 +344,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -377,7 +377,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -408,7 +408,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -460,7 +460,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if ($lockAcquired) { // Wrap in try/finally to ensure lock file gets deleted try { - $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : ''; @@ -472,7 +472,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()); } } finally { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId)); } } } @@ -1476,11 +1476,12 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1516,14 +1517,14 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find resourceId from relevant resources table - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push (not committed by us) and not when branch is created or deleted if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1536,16 +1537,16 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - Authorization::skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); + $authorization->skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId())); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -1574,12 +1575,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1588,7 +1589,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1599,7 +1600,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1786,17 +1787,18 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->inject('platform') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = Authorization::skip(fn () => $dbForPlatform->findOne('repositories', [ + $repository = $authorization->skip(fn () => $dbForPlatform->findOne('repositories', [ Query::equal('$id', [$repositoryId]), Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1814,7 +1816,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1846,7 +1848,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerCommitMessage = $pullRequestResponse['title'] ?? ''; $providerCommitUrl = $pullRequestResponse['html_url'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index ec8cfef775..e335f284b7 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -59,7 +59,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -67,16 +67,16 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = Authorization::skip(function () use ($dbForPlatform, $host, $isMd5) { - if ($isMd5) { - return $dbForPlatform->getDocument('rules', md5($host)); - } - - return $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$host]), - ]) ?? new Document(); - }); + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + } else { + $rule = $authorization->skip( + fn () => $dbForPlatform->find('rules', [ + Query::equal('domain', [$host]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } $errorView = __DIR__ . '/../views/general/error.phtml'; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -111,7 +111,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = Authorization::skip( + $project = $authorization->skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -119,7 +119,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -158,7 +158,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw /** @var Document $deployment */ if (!empty($rule->getAttribute('deploymentId', ''))) { - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); } else { // 1.6.x DB schema compatibility // TODO: Make sure deploymentId is never empty, and remove this code @@ -172,15 +172,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // Document of site or function $resource = $resourceType === 'function' ? - Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : - Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId)); + $authorization->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : + $authorization->skip(fn () => $dbForProject->getDocument('sites', $resourceId)); // ID of active deployments // Attempts to use attribute from both schemas (1.6 and 1.7) $activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', '')); // Get deployment document, as intended originally - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -199,8 +199,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $resource = $type === 'function' ? - Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : - Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); + $authorization->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + $authorization->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); @@ -242,7 +242,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $userExists = false; $userId = $payload['userId'] ?? ''; if (!empty($userId)) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -255,7 +255,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); if (!$project->isEmpty() && isset($user)) { $teamId = $project->getAttribute('teamId', ''); $membership = $user->find('teamId', $teamId, 'memberships'); @@ -862,15 +862,16 @@ App::init() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { /* * Appwrite Router */ $hostname = $request->getHostname() ?? ''; $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain - if (!in_array($hostname, $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1033,7 +1034,8 @@ App::init() ->inject('dbForPlatform') ->inject('queueForCertificates') ->inject('platform') - ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform) { + ->inject('authorization') + ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) { $hostname = $request->getHostname(); $cache = Config::getParam('hostnames', []); $platformHostnames = $platform['hostnames'] ?? []; @@ -1061,64 +1063,64 @@ App::init() } // 4. Check/create rule (requires DB access) - Authorization::disable(); - try { - // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $document = $isMd5 - ? $dbForPlatform->getDocument('rules', md5($domain->get())) - : $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$domain->get()]), + $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) { + try { + // TODO: (@Meldiron) Remove after 1.7.x migration + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $document = $isMd5 + ? $dbForPlatform->getDocument('rules', md5($domain->get())) + : $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]), + ]); + + if (!$document->isEmpty()) { + return; + } + + // 5. Create new rule + $owner = ''; + $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); + $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { + $funcDomain = $fallback; + } + + if ( + (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || + (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) + ) { + $owner = 'Appwrite'; + } + + $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); + $document = new Document([ + '$id' => $ruleId, + 'domain' => $domain->get(), + 'type' => 'api', + 'status' => 'verifying', + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getSequence(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') ]); - if (!$document->isEmpty()) { - return; + $dbForPlatform->createDocument('rules', $document); + + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + $queueForCertificates + ->setDomain($document) + ->setSkipRenewCheck(true) + ->trigger(); + } catch (Duplicate $e) { + Console::info('Certificate already exists'); + } finally { + $cache[$domain->get()] = true; + Config::setParam('hostnames', $cache); } - - // 5. Create new rule - $owner = ''; - $fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); - $funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - $siteDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - - if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) { - $funcDomain = $fallback; - } - - if ( - (!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) || - (!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain)) - ) { - $owner = 'Appwrite'; - } - - $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); - $document = new Document([ - '$id' => $ruleId, - 'domain' => $domain->get(), - 'type' => 'api', - 'status' => 'verifying', - 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), - 'search' => implode(' ', [$ruleId, $domain->get()]), - 'owner' => $owner, - 'region' => $console->getAttribute('region') - ]); - - $dbForPlatform->createDocument('rules', $document); - - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); - $queueForCertificates - ->setDomain($document) - ->setSkipRenewCheck(true) - ->trigger(); - } catch (Duplicate $e) { - Console::info('Certificate already exists'); - } finally { - $cache[$domain->get()] = true; - Config::setParam('hostnames', $cache); - Authorization::reset(); - } + }); }); App::options() @@ -1141,14 +1143,15 @@ App::options() ->inject('devKey') ->inject('apiKey') ->inject('cors') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) { /* * Appwrite Router */ $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1182,7 +1185,8 @@ App::error() ->inject('log') ->inject('queueForStatsUsage') ->inject('devKey') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { + ->inject('authorization') + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Document $devKey, Authorization $authorization) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1264,7 +1268,7 @@ App::error() * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { - if (!DBUser::isPrivileged(Authorization::getRoles())) { + if (!DBUser::isPrivileged($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1326,7 +1330,7 @@ App::error() $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', $authorization->getRoles()); try { /* add queries to log */ @@ -1530,13 +1534,14 @@ App::get('/robots.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1562,13 +1567,14 @@ App::get('/humans.txt') ->inject('platform') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1652,7 +1658,8 @@ App::get('/v1/ping') ->inject('project') ->inject('dbForPlatform') ->inject('queueForEvents') - ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { + ->inject('authorization') + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1664,7 +1671,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - Authorization::skip(function () use ($dbForPlatform, $project) { + $authorization->skip(function () use ($dbForPlatform, $project) { $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 05c08a2231..23bbb12183 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -30,6 +30,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Queue\Publisher; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; @@ -233,7 +234,8 @@ App::init() ->inject('mode') ->inject('team') ->inject('apiKey') - ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) { $route = $utopia->getRoute(); /** @@ -318,7 +320,7 @@ App::init() // Handle special app role case if ($apiKey->getRole() === User::ROLE_APPS) { // Disable authorization checks for API keys - Authorization::setDefaultStatus(false); + $authorization->setDefaultStatus(false); $user = new User([ '$id' => '', @@ -392,14 +394,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - Authorization::setRole($role); - foreach ($user->getRoles() as $authRole) { - Authorization::setRole($authRole); + $authorization->addRole($role); + foreach ($user->getRoles($authorization) as $authRole) { + $authorization->addRole($authRole); } // Step 6: Update project and user last activity @@ -407,7 +409,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -442,7 +444,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -509,14 +511,15 @@ App::init() ->inject('devKey') ->inject('telemetry') ->inject('platform') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform) use ($usageDatabaseListener, $eventDatabaseListener) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -546,7 +549,7 @@ App::init() $closestLimit = null; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = User::isPrivileged($roles); $isAppUser = User::isApp($roles); @@ -657,10 +660,10 @@ App::init() if ($useCache) { $route = $utopia->match($request); $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; - $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged(Authorization::getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged($authorization->getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -677,10 +680,10 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -691,8 +694,7 @@ App::init() } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -703,7 +705,7 @@ App::init() if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -714,11 +716,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -814,8 +816,9 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') + ->inject('authorization') ->inject('timelimit') - ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, callable $timelimit) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -976,11 +979,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', 0); $now = DateTime::now(); if ($cacheLog->isEmpty()) { - Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ + $authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -990,7 +993,7 @@ App::shutdown() ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); - Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); + $authorization->skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); // Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load() $cache->save($key, $data['payload']); } @@ -1002,7 +1005,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index efa733fc34..c0f7494125 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -36,7 +36,8 @@ App::init() ->inject('request') ->inject('project') ->inject('geodb') - ->action(function (App $utopia, Request $request, Document $project, Reader $geodb) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) { $denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', ''); if (!empty($denylist && $project->getId() === 'console')) { $countries = explode(',', $denylist); @@ -49,8 +50,8 @@ App::init() $route = $utopia->match($request); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); - $isAppUser = User::isApp(Authorization::getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = User::isApp($authorization->getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index b7f857da48..5d08c53eee 100644 --- a/app/http.php +++ b/app/http.php @@ -27,7 +27,6 @@ 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\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Pools\Group; @@ -261,7 +260,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools); // create appwrite database, `dbForPlatform` is a direct access call. - createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) { + createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections, $app) { + $authorization = $app->getResource('authorization'); + if ($dbForPlatform->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) { $adapter = new AdapterDatabase($dbForPlatform); $audit = new Audit($adapter); @@ -321,9 +322,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } - if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + $authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('screenshots'), '$collection' => ID::custom('buckets'), 'name' => 'Screenshots', @@ -338,7 +339,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); Console::info(" └── Creating files collection for screenshots bucket..."); $files = $collections['buckets']['files'] ?? []; @@ -366,7 +367,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + $authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -458,8 +459,12 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool App::setResource('pools', fn () => $pools); try { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); + $authorization = $app->getResource('authorization'); + + $request->setAuthorization($authorization); + $response->setAuthorization($authorization); + $authorization->cleanRoles(); + $authorization->addRole(Role::any()->toString()); $app->run($request, $response); } catch (\Throwable $th) { @@ -501,7 +506,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $log->addExtra('file', $th->getFile()); $log->addExtra('line', $th->getLine()); $log->addExtra('trace', $th->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []); $sdk = $route->getLabel("sdk", false); @@ -560,7 +565,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { /** @var Utopia\Database\Database $dbForPlatform */ $dbForPlatform = $app->getResource('dbForPlatform'); - Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { + Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) { try { $time = DateTime::now(); $limit = 1000; @@ -577,7 +582,8 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); + $authorization = $app->getResource('authorization'); + $results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries)); } catch (Throwable $th) { Console::error($th->getMessage()); } diff --git a/app/init/database/filters.php b/app/init/database/filters.php index c9ad3fce03..2b2e17b6a9 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -4,7 +4,6 @@ use Appwrite\OpenSSL\OpenSSL; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\System\System; Database::addFilter( @@ -70,11 +69,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $attributes = $database->find('attributes', [ + $attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), - ]); + ])); foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); @@ -105,12 +104,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('indexes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), - ]); + ])); } ); @@ -120,11 +119,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('platforms', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -134,12 +133,12 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('keys', [ Query::equal('resourceType', ['projects']), Query::equal('resourceInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -149,11 +148,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('devKeys', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -163,11 +162,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('webhooks', [ Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -177,7 +176,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database->find('sessions', [ + return $database->getAuthorization()->skip(fn () => $database->find('sessions', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); @@ -190,7 +189,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -204,7 +203,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('challenges', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -218,7 +217,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('authenticators', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -232,7 +231,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -252,14 +251,14 @@ Database::addFilter( default => ['function', 'site'] }; - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('variables', [ Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', $resourceType), Query::orderAsc('resourceType'), Query::orderAsc(), Query::limit(APP_LIMIT_SUBQUERY), - ]); + ])); } ); @@ -295,11 +294,11 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return $database + return $database->getAuthorization()->skip(fn () => $database ->find('variables', [ Query::equal('resourceType', ['project']), Query::limit(APP_LIMIT_SUBQUERY) - ]); + ])); } ); @@ -332,7 +331,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database + return $database->getAuthorization()->skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) @@ -346,7 +345,7 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { - $targetIds = Authorization::skip(fn () => \array_map( + $targetIds = $database->getAuthorization()->skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ Query::equal('topicInternalId', [$document->getSequence()]), diff --git a/app/init/resources.php b/app/init/resources.php index a3aa3ae47c..371609da97 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -230,7 +230,7 @@ App::setResource('allowedSchemes', function (Document $project) { /** * Rule associated with a request origin. */ -App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project) { +App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) { $domain = \parse_url($request->getOrigin(), PHP_URL_HOST); if (empty($domain)) { return new Document(); @@ -238,7 +238,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do // TODO: (@Meldiron) Remove after 1.7.x migration $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $rule = Authorization::skip(function () use ($dbForPlatform, $domain, $isMd5) { + $rule = $authorization->skip(function () use ($dbForPlatform, $domain, $isMd5) { if ($isMd5) { return $dbForPlatform->getDocument('rules', md5($domain)); } @@ -253,7 +253,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do } return $rule; -}, ['request', 'dbForPlatform', 'project']); +}, ['request', 'dbForPlatform', 'project', 'authorization']); /** * CORS service @@ -321,7 +321,7 @@ App::setResource('redirectValidator', function (Document $devKey, array $allowed return new Redirect($allowedHostnames, $allowedSchemes); }, ['devKey', 'allowedHostnames', 'allowedSchemes']); -App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) { +App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken, $authorization) { /** * Handles user authentication and session validation. * @@ -341,7 +341,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co * overwriting the previous value. */ - Authorization::setDefaultStatus(true); + $authorization->setDefaultStatus(true); $store->setKey('a_session_' . $project->getId()); @@ -408,7 +408,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co } // if (APP_MODE_ADMIN === $mode) { // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { - // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + // $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. // } else { // $user = new Document([]); // } @@ -440,9 +440,9 @@ App::setResource('user', function (string $mode, Document $project, Document $co $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']); -App::setResource('project', function ($dbForPlatform, $request, $console) { +App::setResource('project', function ($dbForPlatform, $request, $console, $authorization) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ @@ -453,10 +453,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $console; } - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForPlatform', 'request', 'console']); +}, ['dbForPlatform', 'request', 'console', 'authorization']); App::setResource('session', function (User $user, Store $store, Token $proofForToken) { if ($user->isEmpty()) { @@ -479,10 +479,6 @@ App::setResource('session', function (User $user, Store $store, Token $proofForT return; }, ['user', 'store', 'proofForToken']); -App::setResource('console', function () { - return new Document(Config::getParam('console')); -}, []); - App::setResource('store', function (): Store { return new Store(); }); @@ -513,7 +509,15 @@ App::setResource('proofForCode', function (): Code { return $code; }); -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + +App::setResource('authorization', function () { + return new Authorization(); +}, []); + +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -529,6 +533,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -550,13 +555,15 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); + +App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { -App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') @@ -566,12 +573,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $database->setDocumentType('users', User::class); return $database; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); -App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { $databases = []; - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -583,13 +590,15 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $configure = (function (Database $database) use ($project, $dsn) { + $configure = (function (Database $database) use ($project, $dsn, $authorization) { $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - $database->setDocumentType('users', User::class); + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES) + ->setDocumentType('users', User::class) + ; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -619,12 +628,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -App::setResource('getLogsDB', function (Group $pools, Cache $cache) { +App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, &$database) { + return function (?Document $project = null) use ($pools, $cache, $authorization, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int) $project->getSequence()); return $database; @@ -634,6 +643,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) @@ -646,7 +656,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); App::setResource('audit', function ($dbForProject) { $adapter = new AdapterDatabase($dbForProject); @@ -845,7 +855,7 @@ App::setResource('promiseAdapter', function ($register) { return $register->get('promiseAdapter'); }, ['register']); -App::setResource('schema', function ($utopia, $dbForProject) { +App::setResource('schema', function ($utopia, $dbForProject, $authorization) { $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); @@ -855,8 +865,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ + $attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) { + $attrs = $authorization->skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -930,7 +940,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { $urls, $params, ); -}, ['utopia', 'dbForProject']); +}, ['utopia', 'dbForProject', 'authorization']); App::setResource('gitHub', function (Cache $cache) { return new VcsGitHub($cache); @@ -958,7 +968,7 @@ App::setResource('smsRates', function () { return []; }); -App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) { +App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform, Authorization $authorization) { $devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', '')); // Check if given key match project's development keys @@ -977,7 +987,7 @@ App::setResource('devKey', function (Request $request, Document $project, array $accessedAt = $key->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DatabaseDateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -994,15 +1004,15 @@ App::setResource('devKey', function (Request $request, Document $project, array /** Update access time as well */ $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $key = $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } return $key; -}, ['request', 'project', 'servers', 'dbForPlatform']); +}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']); -App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request, Authorization $authorization) { $teamInternalId = ''; if ($project->getId() !== 'console') { $teamInternalId = $project->getAttribute('teamInternalId', ''); @@ -1012,7 +1022,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A if (str_starts_with($path, '/v1/projects/:projectId')) { $uri = $request->getURI(); $pid = explode('/', $uri)[3]; - $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); + $p = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); @@ -1021,7 +1031,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -1030,14 +1040,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { + $team = $authorization->skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ Query::equal('$sequence', [$teamInternalId]), ]); }); return $team; -}, ['project', 'dbForPlatform', 'utopia', 'request']); +}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']); App::setResource( 'isResourceBlocked', @@ -1075,7 +1085,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key App::setResource('executor', fn () => new Executor()); -App::setResource('resourceToken', function ($project, $dbForProject, $request) { +App::setResource('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) { $tokenJWT = $request->getParam('token'); if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication @@ -1093,7 +1103,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([]); } - $token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -1111,7 +1121,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { } return match ($token->getAttribute('resourceType')) { - TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { + TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject, $authorization) { $sequences = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); @@ -1122,7 +1132,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { $accessedAt = $token->getAttribute('accessedAt', 0); if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) { $token->setAttribute('accessedAt', DatabaseDateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); + $authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ @@ -1137,8 +1147,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { }; } return new Document([]); -}, ['project', 'dbForProject', 'request']); +}, ['project', 'dbForProject', 'request', 'authorization']); -App::setResource('transactionState', function (Database $dbForProject) { - return new TransactionState($dbForProject); -}, ['dbForProject']); +App::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) { + return new TransactionState($dbForProject, $authorization); +}, ['dbForProject', 'authorization']); diff --git a/app/realtime.php b/app/realtime.php index fab0ce7561..31e6015d92 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -32,7 +32,6 @@ 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\DSN\DSN; use Utopia\Logger\Log; use Utopia\Pools\Group; @@ -309,7 +308,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume 'value' => '{}' ]); - $statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document)); + $statsDocument = $database->getAuthorization()->skip(fn () => $database->createDocument('realtime', $document)); break; } catch (Throwable) { Console::warning("Collection not ready. Retrying connection ({$attempts})..."); @@ -339,7 +338,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume ->setAttribute('timestamp', DateTime::now()) ->setAttribute('value', json_encode($payload)); - Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); + $database->getAuthorization()->skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (Throwable $th) { $logError($th, "updateWorkerDocument"); } @@ -370,7 +369,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $payload = []; - $list = Authorization::skip(fn () => $database->find('realtime', [ + $list = $database->getAuthorization()->skip(fn () => $database->find('realtime', [ Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)), ])); @@ -464,13 +463,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, 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 = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); /** @var Appwrite\Utopia\Database\Documents\User $user */ $user = $database->getDocument('users', $userId); - $roles = $user->getRoles(); + $roles = $user->getRoles($database->getAuthorization()); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -526,6 +525,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); + $authorization = $app->getResource('authorization'); /* * Project Check @@ -537,7 +537,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles())) + && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -573,7 +573,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = $user->getRoles(); + $roles = $user->getRoles($authorization); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -586,6 +586,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $realtime->subscribe($project->getId(), $connection, $roles, $channels); + $realtime->connections[$connection]['authorization'] = $authorization; + $user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ @@ -614,6 +616,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $code = 500; } + $message = $th->getMessage(); // sanitize 0 && 5xx errors @@ -643,12 +646,19 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) { try { $response = new Response(new SwooleResponse()); - $projectId = $realtime->connections[$connection]['projectId']; + $projectId = $realtime->connections[$connection]['projectId'] ?? null; + + // Get authorization from connection (stored during onOpen) + $authorization = $realtime->connections[$connection]['authorization'] ?? null; + $database = getConsoleDB(); + $database->setAuthorization($authorization); if ($projectId !== 'console') { - $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); + $project = $authorization->skip(fn () => $database->getDocument('projects', $projectId)); + $database = getProjectDB($project); + $database->setAuthorization($authorization); } else { $project = null; } @@ -712,10 +722,19 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = $user->getRoles(); + $roles = $user->getRoles($database->getAuthorization()); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); + + // Preserve authorization before subscribe overwrites the connection array + $authorization = $realtime->connections[$connection]['authorization'] ?? null; + $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); + // Restore authorization after subscribe + if ($authorization !== null) { + $realtime->connections[$connection]['authorization'] = $authorization; + } + $user = $response->output($user, Response::MODEL_ACCOUNT); $server->send([$connection], json_encode([ 'type' => 'response', diff --git a/app/worker.php b/app/worker.php index 3720fb85fe..d31e63fc8b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -49,19 +49,30 @@ use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; -Authorization::disable(); Runtime::enableCoroutine(); Server::setResource('register', fn () => $register); -Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { +Server::setResource('authorization', function () { + $authorization = new Authorization(); + $authorization->disable(); + return $authorization; +}, []); + +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, Authorization $authorization) { $pools = $register->get('pools'); $adapter = new DatabasePool($pools->get('console')); $dbForPlatform = new Database($adapter, $cache); - $dbForPlatform->setNamespace('_console'); - $dbForPlatform->setDocumentType('users', User::class); + + $dbForPlatform + ->setAuthorization($authorization) + ->setNamespace('_console') + ->setDocumentType('users', User::class) + ; + + return $dbForPlatform; -}, ['cache', 'register']); +}, ['cache', 'register', 'authorization']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -74,7 +85,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform, Authorization $authorization) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -106,15 +117,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getSequence()); } - $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database + ->setAuthorization($authorization) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform', 'authorization']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -128,7 +141,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - + $database->setAuthorization($authorization); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -165,15 +178,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf ->setNamespace('_' . $project->getSequence()); } - $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + $database + ->setAuthorization($authorization) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache', 'authorization']); -Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { +Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + return function (?Document $project = null) use ($pools, $cache, $database, $authorization) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant((int)$project->getSequence()); return $database; @@ -183,6 +198,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER) @@ -195,7 +211,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day @@ -514,7 +530,8 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) { + ->inject('authorization') + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, Authorization $authorization) use ($worker, $queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); if ($logger) { @@ -530,7 +547,7 @@ $worker $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', Authorization::getRoles()); + $log->addExtra('roles', $authorization->getRoles()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/composer.json b/composer.json index a9c67ede2e..f5bab03697 100644 --- a/composer.json +++ b/composer.json @@ -45,14 +45,14 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.19.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "1.*.*", + "utopia-php/abuse": "1.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "2.0.2-rc3", + "utopia-php/audit": "2.*", "utopia-php/auth": "0.5.*", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", - "utopia-php/config": "1.*.*", - "utopia-php/database": "3.*.*", + "utopia-php/config": "1.*", + "utopia-php/database": "4.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.11.*", "utopia-php/emails": "0.6.*", @@ -64,7 +64,7 @@ "utopia-php/locale": "0.8.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.20.*", - "utopia-php/migration": "1.3.*", + "utopia-php/migration": "1.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 11b00ab631..6fead373dd 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": "0644a7889caffed39ba2c9c5189e45fe", + "content-hash": "33da844fdf5648d1d1a027dfb6ae42bc", "packages": [ { "name": "adhocore/jwt", @@ -3455,25 +3455,24 @@ }, { "name": "utopia-php/abuse", - "version": "1.2.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2" + "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/3339d057c6bb1fa3e5ac5b2598923f6938425ec2", - "reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", + "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", "shasum": "" }, "require": { - "appwrite/appwrite": "19.*.*", "ext-curl": "*", "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "3.*.*" + "utopia-php/database": "*" }, "require-dev": { "laravel/pint": "1.*", @@ -3501,9 +3500,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/1.2.0" + "source": "https://github.com/utopia-php/abuse/tree/1.0.2" }, - "time": "2026-01-05T21:29:10+00:00" + "time": "2025-10-20T07:18:33+00:00" }, { "name": "utopia-php/analytics", @@ -3553,23 +3552,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.2-rc3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "f60a298b516300f56a328403b334b7d62a96e7e7" + "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7", - "reference": "f60a298b516300f56a328403b334b7d62a96e7e7", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/1301ab2607667b9f86456f86895f3e26f8c0c9a7", + "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "3.*", + "utopia-php/database": "4.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3596,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3" + "source": "https://github.com/utopia-php/audit/tree/2.0.4" }, - "time": "2026-01-06T15:32:52+00:00" + "time": "2026-01-14T07:22:46+00:00" }, { "name": "utopia-php/auth", @@ -3899,16 +3898,16 @@ }, { "name": "utopia-php/database", - "version": "3.6.1", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7" + "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", - "reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", + "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", "shasum": "" }, "require": { @@ -3951,9 +3950,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.6.1" + "source": "https://github.com/utopia-php/database/tree/4.5.1" }, - "time": "2025-12-16T09:55:41+00:00" + "time": "2026-01-14T12:07:24+00:00" }, { "name": "utopia-php/detector", @@ -4267,23 +4266,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.36", + "version": "0.33.37", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" + "reference": "30a119d76531d89da9240496940c84fcd9e1758b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", + "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", + "reference": "30a119d76531d89da9240496940c84fcd9e1758b", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4309,9 +4308,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.36" + "source": "https://github.com/utopia-php/http/tree/0.33.37" }, - "time": "2026-01-12T07:32:29+00:00" + "time": "2026-01-13T10:10:21+00:00" }, { "name": "utopia-php/image", @@ -4516,16 +4515,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.13", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715" + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/c5e3f5e970e62e8f7db97b5b90baae2af800a715", - "reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", "shasum": "" }, "require": { @@ -4534,7 +4533,7 @@ "ext-openssl": "*", "php": ">=8.1", "utopia-php/console": "0.0.*", - "utopia-php/database": "3.*", + "utopia-php/database": "4.*", "utopia-php/dsn": "0.2.*", "utopia-php/storage": "0.18.*" }, @@ -4565,9 +4564,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.13" + "source": "https://github.com/utopia-php/migration/tree/1.4.3" }, - "time": "2026-01-07T14:48:05+00:00" + "time": "2026-01-13T09:51:08+00:00" }, { "name": "utopia-php/mongo", @@ -5057,22 +5056,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.6", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" + "reference": "95a937acb393dbf95cccba239d55886e2848ab0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/95a937acb393dbf95cccba239d55886e2848ab0b", + "reference": "95a937acb393dbf95cccba239d55886e2848ab0b", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.36" + "utopia-php/framework": "0.33.37" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5102,9 +5101,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.6" + "source": "https://github.com/utopia-php/swoole/tree/1.0.0" }, - "time": "2026-01-12T07:57:35+00:00" + "time": "2026-01-14T14:00:11+00:00" }, { "name": "utopia-php/system", @@ -5214,16 +5213,16 @@ }, { "name": "utopia-php/validators", - "version": "0.1.0", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", "shasum": "" }, "require": { @@ -5231,7 +5230,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", + "phpstan/phpstan": "2.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5253,9 +5252,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.1.0" + "source": "https://github.com/utopia-php/validators/tree/0.2.0" }, - "time": "2025-11-18T11:05:46+00:00" + "time": "2026-01-13T09:16:51+00:00" }, { "name": "utopia-php/vcs", @@ -8988,9 +8987,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/audit": 5 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 23dc6fc2e9..8e098774e6 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -20,10 +20,12 @@ use Utopia\Database\Validator\Authorization; class TransactionState { private Database $dbForProject; - - public function __construct(Database $dbForProject) + private Authorization $authorization; + /** @var Authorization $authorization */ + public function __construct(Database $dbForProject, Authorization $authorization) { $this->dbForProject = $dbForProject; + $this->authorization = $authorization; } @@ -342,12 +344,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + $transaction = $this->authorization->skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') { return []; } - $operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [ + $operations = $this->authorization->skip(fn () => $this->dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index bc37924db6..ea51225ba6 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -100,8 +100,6 @@ abstract class Migration public function __construct() { - Authorization::disable(); - Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -129,6 +127,7 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -136,6 +135,9 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; + $authorization->disable(); + $authorization->setDefaultStatus(false); + return $this; } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index 1ff2f8f706..bf7d01764f 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -21,7 +21,7 @@ class Action extends PlatformAction return \dirname(__DIR__, 6); } - protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response): void + protected function avatar(string $type, string $code, int $width, int $height, int $quality, Response $response): void { $code = \strtolower($code); $type = \strtolower($type); @@ -58,10 +58,10 @@ class Action extends PlatformAction unset($image); } - protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger): array + protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array { try { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -112,7 +112,7 @@ class Action extends PlatformAction ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); + $authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -120,7 +120,7 @@ class Action extends PlatformAction do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php index 04648752b5..637ea647ef 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Browsers/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('browsers', $code, $width, $height, $quality, $response); + $this->avatar('browsers', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index 1c0de4001e..a6a013ef21 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -68,7 +69,7 @@ class Get extends Action $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index 9d53991dd6..f8e7a35b05 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -69,7 +70,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index f7c983db78..37776a3466 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -53,12 +53,13 @@ class Get extends Action ->inject('contributors') ->inject('employees') ->inject('logger') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -73,7 +74,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php index 5d3429b377..87357f14c7 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/CreditCards/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('credit-cards', $code, $width, $height, $quality, $response); + $this->avatar('credit-cards', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php index c3960c134e..8230b15f50 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Flags/Get.php @@ -59,6 +59,6 @@ class Get extends Action public function action(string $code, int $width, int $height, int $quality, Response $response) { - $this->avatarCallback('flags', $code, $width, $height, $quality, $response); + $this->avatar('flags', $code, $width, $height, $quality, $response); } } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 47afc90986..33b69dd589 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -13,6 +13,7 @@ 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\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; @@ -142,7 +143,7 @@ class Base extends Action return $deployment; } - public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document + public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = ''): Document { $deploymentId = ID::unique(); $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); @@ -239,7 +240,7 @@ class Base extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -265,7 +266,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -302,7 +303,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -328,6 +329,8 @@ class Base extends Action } } + $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) @@ -336,4 +339,34 @@ class Base extends Action return $deployment; } + + /** + * Update empty manual rule for deployment. + * In case of first deployment, deployment ID will be empty in the rules, so we need to update it here. + * + * @param \Utopia\Database\Document $project + * @param \Utopia\Database\Document $resource + * @param \Utopia\Database\Document $deployment + * @param \Utopia\Database\Database $dbForPlatform + * @return void + */ + public static function updateEmptyManualRule(Document $project, Document $resource, Document $deployment, Database $dbForPlatform, Authorization $authorization) + { + $resourceType = $resource->getCollection() === 'sites' ? 'site' : 'function'; + + $queries = [ + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), + Query::equal('deploymentResourceType', [$resourceType]), + Query::equal('deploymentId', ['']), + Query::equal('type', ['deployment']), + Query::equal('trigger', ['manual']), + ]; + $dbForPlatform->forEach('rules', function (Document $rule) use ($deployment, $dbForPlatform, $authorization) { + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([ + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getSequence(), + ]))); + }, $queries); + } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index aa43b12125..1468bf71ac 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -60,6 +60,7 @@ class Get extends Action ->inject('response') ->inject('dbForPlatform') ->inject('platform') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,7 +69,8 @@ class Get extends Action string $type, Response $response, Database $dbForPlatform, - array $platform + array $platform, + Authorization $authorization, ) { $domains = $platform['hostnames'] ?? []; if ($type === 'rules') { @@ -121,7 +123,7 @@ class Get extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $document = $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$value]), ])); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 83a401a35e..e2df5d92e6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -292,7 +292,7 @@ abstract class Action extends UtopiaAction }; } - protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document + protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): Document { $key = $attribute->getAttribute('key'); $type = $attribute->getAttribute('type', ''); @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException(), params: [$type]); } - $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, params: [$databaseId]); @@ -371,7 +371,7 @@ abstract class Action extends UtopiaAction \in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) && $attribute->getAttribute('required') ) { - $hasData = !Authorization::skip(fn () => $dbForProject + $hasData = !$authorization->skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -472,9 +472,9 @@ abstract class Action extends UtopiaAction return $attribute; } - protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document + protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index f04532aeee..442461fdd3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -81,7 +83,7 @@ class Create extends Action 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 003b4227c9..92324aae70 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -68,10 +69,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -79,6 +81,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_BOOLEAN, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index c2982445a4..bd3108a871 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index 984d4b0245..2518875424 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_DATETIME, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 649cde10aa..37ae2a7bfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -67,12 +67,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index b36072eb75..a36e264e50 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 382f16b469..609a337625 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_EMAIL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 9145191b0c..3c47d1fdfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -73,10 +74,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { if (!is_null($default) && !\in_array($default, $elements, true)) { throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); @@ -98,7 +100,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 2f47eb0cc6..5bea5230c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_ENUM, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 56d8874794..0dc11bd76c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,10 +75,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $min ??= -PHP_FLOAT_MAX; $max ??= PHP_FLOAT_MAX; @@ -100,7 +102,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 330c649f27..20b5c0767d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_FLOAT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 3a8eece531..436b22c6c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -68,12 +68,13 @@ class Get extends Action ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 2340d1d55d..2adf3977f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,10 +71,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute( $databaseId, @@ -90,7 +92,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index 236dbf7f83..eccf18b005 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_IP, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 1be4df10c7..0989bb2904 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -74,10 +75,11 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $min ??= \PHP_INT_MIN; $max ??= \PHP_INT_MAX; @@ -102,7 +104,7 @@ class Create extends Action 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $formatOptions = $attribute->getAttribute('formatOptions', []); if (!empty($formatOptions)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index ebb275ae63..57797d3e03 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,10 +72,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -82,6 +84,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_INTEGER, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index f0fd728902..fc846957b0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_LINESTRING, 'required' => $required, 'default' => $default - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 3407da2b34..8fff545921 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_LINESTRING, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index f2e4d19267..a89c21581d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POINT, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index 86e78e56e3..9561fe6b96 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_POINT, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 4c49b21050..54da3ac604 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,17 +70,18 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_POLYGON, 'required' => $required, 'default' => $default, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index 0dbb117cec..b82a3d4be0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; @@ -69,10 +70,11 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -80,6 +82,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_POLYGON, default: $default, required: $required, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index b43568a968..615e64dfd7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -83,16 +83,17 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { $key ??= $relatedCollectionId; $twoWayKeyWasProvided = $twoWayKey !== null; $twoWayKey ??= $collectionId; - $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, params: [$databaseId]); } @@ -154,7 +155,7 @@ class Create extends Action 'twoWayKey' => $twoWayKey, 'onDelete' => $onDelete, ] - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); foreach ($attribute->getAttribute('options', []) as $k => $option) { $attribute->setAttribute($k, $option); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index feed58a4ff..d180131a44 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -71,6 +72,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -82,7 +84,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -90,6 +93,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_RELATIONSHIP, required: false, options: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index b42558f063..b3fe03cace 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -77,6 +78,7 @@ class Create extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -93,7 +95,8 @@ class Create extends Action Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, - array $plan + array $plan, + Authorization $authorization ): void { if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.'); @@ -132,7 +135,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $attribute->setAttribute('encrypt', $encrypt); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 53ea2a0e03..37547f3da8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -72,6 +73,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -85,7 +87,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( databaseId: $databaseId, @@ -93,6 +96,7 @@ class Update extends Action key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, + authorization: $authorization, type: Database::VAR_STRING, size: $size, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index 7529845016..ed1a23acf5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,6 +71,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -83,7 +85,8 @@ class Create extends Action UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -93,7 +96,7 @@ class Create extends Action 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 9ba8ebb859..08f7a26fd9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,6 +70,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -81,7 +83,8 @@ class Update extends Action ?string $newKey, UtopiaResponse $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ): void { $attribute = $this->updateAttribute( $databaseId, @@ -89,6 +92,7 @@ class Update extends Action $key, $dbForProject, $queueForEvents, + $authorization, type: Database::VAR_STRING, filter: APP_DATABASE_ATTRIBUTE_URL, default: $default, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 6bfe5f8913..61c5b295cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -64,12 +64,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 724f40f00e..89cc14056a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -85,12 +85,13 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index af36649061..fd2c419954 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -64,12 +64,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index f16d00998d..ec65135a05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -258,9 +258,9 @@ abstract class Action extends DatabasesAction Document $collection, Document $document, Database $dbForProject, - /* options */ array &$collectionsCache, + Authorization $authorization, ?int &$operations = null, ): bool { @@ -297,7 +297,7 @@ abstract class Action extends DatabasesAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = Authorization::skip( + $relatedCollectionDoc = $authorization->skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId @@ -323,7 +323,8 @@ abstract class Action extends DatabasesAction document: $relation, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations + operations: $operations, + authorization: $authorization ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 53831f0fc5..16b7bd1b25 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -85,20 +85,21 @@ class Decrement extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $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, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -106,7 +107,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index ea680db3b1..7adae7633b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -85,20 +85,21 @@ class Increment extends Action ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $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, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -106,7 +107,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6ec06f5c8a..bbc63da499 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -24,6 +24,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -132,9 +133,10 @@ class Create extends Action ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void { $data = \is_string($data) ? \json_decode($data, true) @@ -178,19 +180,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -204,7 +206,7 @@ class Create extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext()); } - $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, @@ -247,8 +249,8 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + if (!$authorization->hasRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')'); } } } @@ -259,21 +261,25 @@ class Create extends Action $operations = 0; - $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations) { + $checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations, $authorization) { $operations++; $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validator = new Authorization($permission); - $valid = $validator->isValid($collection->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + $validCollection = $authorization->isValid( + new Input($permission, $collection->getPermissionsByType($permission)) + ); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($document->getUpdate()); + $validDocument = $authorization->isValid( + new Input($permission, $document->getUpdate()) + ); + $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } } @@ -298,7 +304,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -314,7 +320,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = Authorization::skip( + $current = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -369,7 +375,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -468,6 +474,7 @@ class Create extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index faae638c88..7acf8e386e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -83,6 +83,7 @@ class Delete extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,18 +98,19 @@ class Delete extends Action Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, - array $plan + array $plan, + Authorization $authorization ): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -121,7 +123,7 @@ class Delete extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -131,7 +133,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -205,6 +207,7 @@ class Delete extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index f560267d4b..cb8b0dd42e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -70,20 +70,21 @@ class Get extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -125,6 +126,7 @@ class Get extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization, operations: $operations ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index a4dd38ef67..2f5579f0ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -72,13 +72,14 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 707857347a..a92d8ec180 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -87,10 +87,11 @@ class Update extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -98,16 +99,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); @@ -125,7 +126,7 @@ class Update extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -140,7 +141,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -153,7 +154,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -171,7 +172,7 @@ class Update extends Action $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { $operations++; $relationships = \array_filter( @@ -195,7 +196,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -212,7 +213,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -249,7 +250,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -340,6 +341,7 @@ class Update extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization, ); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index b32871add2..62e59dd010 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -91,10 +91,11 @@ class Upsert extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -106,15 +107,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -139,7 +140,7 @@ class Upsert extends Action // Use transaction-aware document retrieval to see changes from same transaction $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -155,7 +156,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -168,7 +169,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -181,7 +182,7 @@ class Upsert extends Action $newDocument = new Document($data); $operations = 0; - $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) { + $setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) { $operations++; $relationships = \array_filter( @@ -205,7 +206,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -222,7 +223,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -259,7 +260,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -361,6 +362,7 @@ class Upsert extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, + authorization: $authorization ); $relationships = \array_map( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 8b770284c3..ff94e67b02 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -74,20 +74,21 @@ class XList extends Action ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException(), params: [$collectionId]); } @@ -115,7 +116,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); @@ -161,7 +162,8 @@ class XList extends Action document: $document, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations, + authorization: $authorization, + operations: $operations ); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index e7909772a5..d8df8f1f8c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -57,12 +57,13 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 872b7348fe..5b035a8688 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -79,12 +79,13 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 27b28e866c..d9f9f66504 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -70,12 +70,13 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index d66bf8f38f..661f259910 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -59,12 +59,13 @@ class Get extends Action ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index abbdefb4d5..90826ffbe3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -66,13 +66,14 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { /** @var Document $database */ - $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, params: [$databaseId]); @@ -112,7 +113,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = $authorization->skip(fn () => $dbForProject->find('indexes', [ Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 0f5a57c6e9..0b6e47a798 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -71,13 +71,14 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void { - $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, params: [$databaseId]); @@ -112,9 +113,9 @@ class XList extends Action $detector = new Detector($log['userAgent']); $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); + $os = $detector->getOS() ?: []; + $client = $detector->getClient() ?: []; + $device = $detector->getDevice() ?: []; $output[$i] = new Document([ 'event' => $log['event'], @@ -122,20 +123,20 @@ class XList extends Action 'userEmail' => $log['data']['userEmail'] ?? null, 'userName' => $log['data']['userName'] ?? null, 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] + 'ip' => $log['ip'] ?? null, + 'time' => $log['time'] ?? null, + 'osCode' => $os['osCode'] ?? null, + 'osName' => $os['osName'] ?? null, + 'osVersion' => $os['osVersion'] ?? null, + 'clientType' => $client['clientType'] ?? null, + 'clientCode' => $client['clientCode'] ?? null, + 'clientName' => $client['clientName'] ?? null, + 'clientVersion' => $client['clientVersion'] ?? null, + 'clientEngine' => $client['clientEngine'] ?? null, + 'clientEngineVersion' => $client['clientEngineVersion'] ?? null, + 'deviceName' => $device['deviceName'] ?? null, + 'deviceBrand' => $device['deviceBrand'] ?? null, + 'deviceModel' => $device['deviceModel'] ?? null ]); $record = $geodb->get($log['ip']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index e319a33e67..304ce5c88e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -71,12 +71,13 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { - $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, params: [$databaseId]); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index c4a46650c9..0552a31509 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -63,10 +63,11 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); @@ -83,7 +84,7 @@ class Get extends Action str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index b0b0385bf5..c23286f3cd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -67,12 +67,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $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, params: [$databaseId]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php index 20c71223c6..4ca20f8414 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -55,10 +55,11 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('authorization') ->callback($this->action(...)); } - public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user): void + public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, Authorization $authorization): void { $permissions = []; if (!empty($user->getId())) { @@ -73,7 +74,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ + $transaction = $authorization->skip(fn () => $dbForProject->createDocument('transactions', new Document([ '$id' => ID::unique(), '$permissions' => $permissions, 'status' => 'pending', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php index 5a2568db0c..f09ed2bc27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -18,6 +18,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -63,21 +64,22 @@ class Create extends Action ->inject('dbForProject') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan): void + public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization): void { if (empty($operations)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -113,13 +115,13 @@ class Create extends Action throw new Exception(Exception::USER_UNAUTHORIZED); } - $database = $databases[$operation['databaseId']] ??= Authorization::skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); + $database = $databases[$operation['databaseId']] ??= $authorization->skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$operation['databaseId']]); } $collection = $collections[$operation[$this->getGroupId()]] ??= - Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND, params: [$operation[$this->getGroupId()]]); @@ -165,14 +167,20 @@ class Create extends Action // For individual operations, enforce permissions unless using API key/admin if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validator = new Authorization($permissionType); - $collectionValid = $validator->isValid($collection->getPermissionsByType($permissionType)); + + $collectionValid = $authorization->isValid( + new Input($permissionType, $collection->getPermissionsByType($permissionType)) + ); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $validator->isValid($document->getUpdate()); + $documentValid = $authorization->isValid( + new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) + ); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $validator->isValid($document->getDelete()); + $documentValid = $authorization->isValid( + new Input(Database::PERMISSION_DELETE, $document->getDelete()) + ); } } @@ -189,7 +197,7 @@ class Create extends Action // Users can only set permissions for roles they have if (isset($operation['data']['$permissions'])) { $permissions = $operation['data']['$permissions']; - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -201,7 +209,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -230,7 +238,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { $dbForProject->createDocuments('transactionLogs', $staged); return $dbForProject->increaseDocumentAttribute( 'transactions', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php index 9235c81b8e..e4f1051464 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -76,6 +76,7 @@ class Update extends Action ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('authorization') ->callback($this->action(...)); } @@ -102,7 +103,7 @@ class Update extends Action * @throws Structure * @throws \Utopia\Exception */ - public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void + public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization): void { if (!$commit && !$rollback) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); @@ -111,11 +112,11 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]); @@ -138,12 +139,12 @@ class Update extends Action $currentDocumentId = null; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) { + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -167,7 +168,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = Authorization::skip( + $collections[$collectionId] = $authorization->skip( fn () => $dbForProject->getCollection($collectionId) ); } @@ -232,7 +233,7 @@ class Update extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -243,33 +244,33 @@ class Update extends Action ->setDocument($transaction); }); } catch (NotFoundException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e, params: [$currentDocumentId ?? 'unknown']); } catch (DuplicateException | ConflictException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_CONFLICT, previous: $e); } catch (StructureException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (LimitException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, $e->getMessage()); } catch (TransactionException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::TRANSACTION_FAILED, $e->getMessage()); } catch (QueryException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); @@ -297,11 +298,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ + $database = $authorization->skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = $authorization->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -393,7 +394,7 @@ class Update extends Action } if ($rollback) { - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'failed']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index a717b00ae4..a1aa7a70b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -59,10 +59,11 @@ class Get extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); @@ -81,7 +82,7 @@ class Get extends Action str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index c13149cfc7..757f845c68 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -56,10 +56,11 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, UtopiaResponse $response, Database $dbForProject): void + public function action(string $range, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { $periods = Config::getParam('usage', []); @@ -74,7 +75,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php index c0d502d10a..eede1b221b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php @@ -60,6 +60,7 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php index c5939b6974..cd8d392cfc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php @@ -61,6 +61,7 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php index 63693abb67..79722efee1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php @@ -62,6 +62,7 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php index b022d0ed85..c39681a743 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php @@ -63,6 +63,7 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php index 8a691a6e98..da63b0cef7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php @@ -58,6 +58,7 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php index 6d19f99b7b..51e7f295a1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php @@ -61,6 +61,7 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php index 48a04304bd..daca13d587 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php @@ -62,6 +62,7 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php index bd280a2910..4d5881c81e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php @@ -64,6 +64,7 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php index ac5c1cf907..122671adc5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php @@ -65,6 +65,7 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php index 8293d66992..cd898fa0bf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php @@ -63,6 +63,7 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php index bf2815db45..ee9c5f6cb1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php @@ -64,6 +64,7 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php index ee88ac8683..39dafbd1a6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php @@ -61,6 +61,7 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php index 9b38cd9dfd..80c764b4c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php @@ -61,6 +61,7 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php index 7db8625ebf..54ed029c71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php @@ -62,6 +62,7 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index a29d728437..f590e8bdbb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -63,6 +63,7 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index 7621dc6dda..83b6f1bfc6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -64,6 +64,7 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php index 6110d6ee07..227fece7de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php @@ -61,6 +61,7 @@ class Create extends LineCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php index afd0098152..b0e433da5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php @@ -63,6 +63,7 @@ class Update extends LineUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php index 084adca860..3fc5865905 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php @@ -61,6 +61,7 @@ class Create extends PointCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 632be85871..040b8171d7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php @@ -63,6 +63,7 @@ class Update extends PointUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php index 723940af58..630340ba7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php @@ -61,6 +61,7 @@ class Create extends PolygonCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 91b55f74b4..43b4a4e6a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php @@ -63,6 +63,7 @@ class Update extends PolygonUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php index f3933160c0..7f28a3cdb7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php @@ -73,6 +73,7 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index eb87713457..fd7fdab8de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php @@ -65,6 +65,7 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php index 9279409e88..ff50313a7c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php @@ -66,6 +66,7 @@ class Create extends StringCreate ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 9fffa71b33..6ad1be124b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php @@ -65,6 +65,7 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php index 50f5ea5d5b..b19d6e80a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php @@ -61,6 +61,7 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index b52ea66ce1..dce11964e8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php @@ -62,6 +62,7 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 39551e5113..13ebe14682 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -52,6 +52,7 @@ class XList extends AttributesXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php index 7287c2cb3e..bd08ad5617 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -67,6 +67,7 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php index d4af8b3508..925a7b2494 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php @@ -55,6 +55,7 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php index 4286ee07ca..ad83291815 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php @@ -50,6 +50,7 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index 727334b6da..09720f4d71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php @@ -66,6 +66,8 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } + } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php index 7d187ab5a1..7fa8073d1e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php @@ -61,6 +61,7 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php index 75ee507aa8..246d569825 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php @@ -52,6 +52,7 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index bf5f27e388..1dc2d3ea43 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -54,6 +54,7 @@ class XList extends IndexXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php index 5eab050b7e..79691436e4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php @@ -50,6 +50,7 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php index accb0392fe..b9896d282d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php @@ -66,6 +66,7 @@ class Delete extends DocumentsDelete ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php index fea59b8b13..f4ccea1698 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php @@ -68,6 +68,7 @@ class Update extends DocumentsUpdate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php index 492af25e9f..69a687d92f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php @@ -68,6 +68,7 @@ class Upsert extends DocumentsUpsert ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php index 42f2919ce1..a660b008e1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php @@ -67,6 +67,7 @@ class Decrement extends DecrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php index 3d04d71c26..c2b69429ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php @@ -67,6 +67,7 @@ class Increment extends IncrementDocumentAttribute ->inject('queueForEvents') ->inject('queueForStatsUsage') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php index b5491a593b..c70ed71378 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php @@ -111,6 +111,7 @@ class Create extends DocumentCreate ->inject('queueForFunctions') ->inject('queueForWebhooks') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php index bcd8682a48..1763491c19 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php @@ -70,6 +70,7 @@ class Delete extends DocumentDelete ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php index 450fb4d746..bb24e93de0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php @@ -58,6 +58,7 @@ class Get extends DocumentGet ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php index 27bd82195d..86bfcfec85 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php @@ -51,6 +51,7 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->inject('audit') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php index fe4ffc4995..0879055a78 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php @@ -69,6 +69,7 @@ class Update extends DocumentUpdate ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index 0fbaa921cb..99e0487c93 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -72,6 +72,7 @@ class Upsert extends DocumentUpsert ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index c51017fa75..230d391110 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -59,6 +59,7 @@ class XList extends DocumentXList ->inject('dbForProject') ->inject('queueForStatsUsage') ->inject('transactionState') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php index 03316783cd..0d3bc9afc1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -62,6 +62,7 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php index 0fb44ee94a..b8be7edd56 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php @@ -52,6 +52,7 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index e0c590379b..5532203d0a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -55,6 +55,7 @@ class XList extends CollectionXList ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php index 27454664f4..e7e5f0132f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php @@ -50,6 +50,7 @@ class Create extends TransactionsCreate ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php index 4668ae2d15..1228c83e30 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php @@ -54,6 +54,7 @@ class Create extends OperationsCreate ->inject('dbForProject') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php index 4337a8d28d..8be28ce9f7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php @@ -60,6 +60,7 @@ class Update extends TransactionsUpdate ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php index 89b9fbd8c2..87be8a9eab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/Get.php @@ -48,6 +48,7 @@ class Get extends DatabaseUsageGet ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php index 0bd96fc40a..2cde337f5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Usage/XList.php @@ -46,6 +46,7 @@ class XList extends DatabaseUsageXList ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index e7e34d4c5b..c5ae08728d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -17,6 +17,7 @@ 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\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -88,6 +89,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -105,7 +107,8 @@ class Create extends Action Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index 0aaea3bd4a..acfaa965ac 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -15,6 +15,7 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -77,6 +78,7 @@ class Create extends Base ->inject('project') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -95,7 +97,8 @@ class Create extends Base Event $queueForEvents, Document $project, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -127,7 +130,9 @@ class Create extends Base queueForBuilds: $queueForBuilds, template: $template, github: $github, - activate: $activate + activate: $activate, + referenceType: $type, + reference: $reference ); $queueForEvents @@ -170,6 +175,9 @@ class Create extends Base ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); + + $this->updateEmptyManualRule($project, $function, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php index 69594c3d86..25dce63b38 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -87,7 +87,7 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, ) { $function = $dbForProject->getDocument('functions', $functionId); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 81f55ba829..1a265298d3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -29,6 +29,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -99,6 +100,7 @@ class Create extends Base ->inject('proofForToken') ->inject('executor') ->inject('platform') + ->inject('authorization') ->callback($this->action(...)); } @@ -123,7 +125,8 @@ class Create extends Base Store $store, Token $proofForToken, Executor $executor, - array $platform + array $platform, + Authorization $authorization, ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -161,10 +164,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -180,7 +183,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); @@ -194,10 +197,8 @@ class Create extends Base throw new Exception(Exception::BUILD_NOT_READY); } - $validator = new Authorization('execute'); - - if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + if (!$authorization->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $jwt = ''; // initialize @@ -295,7 +296,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -336,7 +337,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -488,7 +489,7 @@ class Create extends Base ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } $executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId(); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index 9a93e5a342..c7a9a6d330 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -61,6 +61,7 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Delete extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -108,7 +110,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 6bd0a3675e..c5eebe139e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -52,6 +52,7 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -59,12 +60,13 @@ class Get extends Base string $functionId, string $executionId, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 20680e87ff..ff381e1f3d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -60,6 +60,7 @@ class XList extends Base ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,12 +69,13 @@ class XList extends Base array $queries, bool $includeTotal, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index 5c226c5925..6ad488283e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -115,6 +115,7 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -152,7 +153,8 @@ class Create extends Base Func $queueForFunctions, Database $dbForPlatform, Request $request, - GitHub $github + GitHub $github, + Authorization $authorization ) { // Temporary abuse check @@ -237,7 +239,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = Authorization::skip( + $schedule = $authorization->skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -315,6 +317,7 @@ class Create extends Base template: $template, github: $github, activate: true, + authorization: $authorization, reference: $providerBranch, referenceType: 'branch' ); @@ -366,7 +369,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - $rule = Authorization::skip( + $rule = $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index dfa6636554..9cafc17bbe 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -61,6 +61,7 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Delete extends Base Database $dbForProject, DeleteEvent $queueForDeletes, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -87,7 +89,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index b6dcfd6cf8..aeccf98a02 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -62,6 +62,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,7 +73,8 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -101,7 +103,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -112,12 +114,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index adb29bc533..55c5b30418 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -104,6 +104,7 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') + ->inject('authorization') ->callback($this->action(...)); } @@ -134,7 +135,8 @@ class Update extends Base Build $queueForBuilds, Database $dbForPlatform, GitHub $github, - Executor $executor + Executor $executor, + Authorization $authorization ) { // TODO: If only branch changes, re-deploy $function = $dbForProject->getDocument('functions', $functionId); @@ -282,7 +284,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents->setParam('functionId', $function->getId()); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index acb6995d6f..1fa65d0cc9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -55,10 +55,11 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $functionId, string $range, Response $response, Database $dbForProject) + public function action(string $functionId, string $range, Response $response, Database $dbForProject, Authorization $authorization) { $function = $dbForProject->getDocument('functions', $functionId); @@ -83,7 +84,7 @@ class Get extends Base str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index 6a4ded4db7..38a95d4469 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -52,10 +52,11 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -75,7 +76,7 @@ class XList extends Base str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 815f1bd8fc..5438479d40 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -65,6 +65,7 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -76,7 +77,8 @@ class Create extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Document $project + Document $project, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -119,7 +121,7 @@ class Create extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 50c1de4232..161eed3112 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -57,6 +57,7 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -65,7 +66,8 @@ class Delete extends Base string $variableId, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -92,7 +94,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 5c1f5809cd..6af5ac90c2 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -62,6 +62,7 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -73,7 +74,8 @@ class Update extends Base ?bool $secret, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -110,7 +112,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 414696306f..8f041dd57b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -25,7 +25,6 @@ use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Detector\Detection\Rendering\SSR; use Utopia\Detector\Detection\Rendering\XStatic; use Utopia\Detector\Detector\Rendering; @@ -1121,7 +1120,7 @@ class Builds extends Action ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $resource->getAttribute('schedule')) ->setAttribute('active', !empty($resource->getAttribute('schedule')) && !empty($resource->getAttribute('deploymentId'))); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } Console::info('Deployment action finished'); @@ -1350,7 +1349,6 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception - * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1439,11 +1437,11 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $rule = $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal("deploymentInternalId", [$deployment->getSequence()]), - ])); + ]); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $previewUrl = match($resource->getCollection()) { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 4ba51bca37..3de0322d6e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -87,6 +87,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -106,7 +107,8 @@ class Create extends Action Device $deviceForSites, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -276,7 +278,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -341,7 +343,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -366,6 +368,8 @@ class Create extends Action } } + + $metadata = null; $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 2f9b1bdfde..9554e2aa14 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -65,6 +65,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') + ->inject('authorization') ->callback($this->action(...)); } @@ -78,7 +79,8 @@ class Create extends Action Database $dbForPlatform, Event $queueForEvents, Build $queueForBuilds, - Device $deviceForSites + Device $deviceForSites, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -147,7 +149,7 @@ class Create extends Action $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 5f1d446809..30d5e779c1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -79,6 +79,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,7 +98,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -130,6 +132,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, ); $queueForEvents @@ -189,7 +192,7 @@ class Create extends Base $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; $ruleId = $isMd5 ? md5($domain) : ID::unique(); - Authorization::skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -209,6 +212,8 @@ class Create extends Base ])) ); + $this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index 915e3c5c9f..feff28427e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -72,6 +73,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -87,7 +89,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -110,6 +113,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, reference: $reference, referenceType: $type ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index f962d0118d..b5d956128b 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -60,6 +60,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -70,7 +71,8 @@ class Update extends Base Response $response, Database $dbForProject, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -104,12 +106,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment, $authorization) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }, $queries)); $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index af96c10457..5c274d6a20 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -55,6 +55,7 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -62,7 +63,8 @@ class Get extends Base string $siteId, string $range, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -91,7 +93,7 @@ class Get extends Base ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index d36cc56ae5..a90cb0cab9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -52,10 +52,11 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -78,7 +79,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index ed5c23b6c1..4757461a98 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -22,6 +22,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -90,6 +91,7 @@ class Create extends Action ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') + ->inject('authorization') ->callback($this->action(...)); } @@ -105,26 +107,26 @@ class Create extends Action Event $queueForEvents, string $mode, Device $deviceForFiles, - Device $deviceForLocal + Device $deviceForLocal, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $allowedPermissions = [ - \Utopia\Database\Database::PERMISSION_READ, - \Utopia\Database\Database::PERMISSION_UPDATE, - \Utopia\Database\Database::PERMISSION_DELETE, + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, ]; // Map aggregate permissions to into the set of individual permissions they represent. @@ -141,7 +143,7 @@ class Create extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser) { foreach (\Utopia\Database\Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -154,7 +156,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -379,11 +381,10 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } // Trigger after create success hook @@ -427,13 +428,12 @@ class Create extends Action * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index eccacaafd2..ca376842e2 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -64,6 +65,7 @@ class Delete extends Action ->inject('queueForEvents') ->inject('deviceForFiles') ->inject('queueForDeletes') + ->inject('authorization') ->callback($this->action(...)); } @@ -75,33 +77,33 @@ class Delete extends Action Event $queueForEvents, Device $deviceForFiles, DeleteEvent $queueForDeletes, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_DELETE); - $valid = $validator->isValid($bucket->getDelete()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $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())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if ($fileSecurity && !$valid && !$authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $deviceDeleted = false; @@ -125,7 +127,7 @@ class Delete extends Action if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = $authorization->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index 45e3b83375..bbceff51ec 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -68,6 +69,7 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -80,13 +82,14 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization, ) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -94,17 +97,16 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index 77f163e5fb..caaab29efc 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -10,6 +10,7 @@ use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -49,6 +50,7 @@ class Get extends Action ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -57,27 +59,27 @@ class Get extends Action string $fileId, Response $response, Database $dbForProject, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 9c4e49d0bb..7ab3e713bc 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -17,6 +17,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Image\Image; use Utopia\Platform\Action; @@ -90,6 +91,7 @@ class Get extends Action ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -114,7 +116,8 @@ class Get extends Action Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, - Document $project + Document $project, + Authorization $authorization ) { if (!\extension_loaded('imagick')) { @@ -122,10 +125,10 @@ class Get extends Action } /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -137,17 +140,16 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -269,11 +271,11 @@ class Get extends Action $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!User::isPrivileged(Authorization::getRoles())) { + if (!User::isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php index 67372435b1..516343e23f 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('project') ->inject('mode') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -64,7 +65,8 @@ class Get extends Action Database $dbForPlatform, Document $project, string $mode, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization ) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -86,15 +88,15 @@ class Get extends Action $disposition = $decoded['disposition'] ?? 'inline'; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index be78cc358b..57856c1564 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -14,6 +14,7 @@ use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -62,6 +63,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,26 +74,26 @@ class Update extends Action ?array $permissions, Response $response, Database $dbForProject, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $valid = $validator->isValid($bucket->getUpdate()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -105,7 +107,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $authorization->getRoles(); if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -118,7 +120,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -139,7 +141,7 @@ class Update extends Action if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index 41ee95b165..3874fedacf 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -15,6 +15,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -69,6 +70,7 @@ class Get extends Action ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') + ->inject('authorization') ->callback($this->action(...)); } @@ -81,13 +83,14 @@ class Get extends Action Database $dbForProject, string $mode, Document $resourceToken, - Device $deviceForFiles + Device $deviceForFiles, + Authorization $authorization ) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -95,17 +98,16 @@ class Get extends Action $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index e46fdb2a0a..3663b56fab 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -16,6 +16,7 @@ use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -61,6 +62,7 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('mode') + ->inject('authorization') ->callback($this->action(...)); } @@ -71,22 +73,22 @@ class XList extends Action bool $includeTotal, Response $response, Database $dbForProject, - string $mode + string $mode, + Authorization $authorization ) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(\Utopia\Database\Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } try { @@ -119,7 +121,7 @@ class XList extends Action if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -136,8 +138,8 @@ class XList extends Action $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $includeTotal ? Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; + $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $includeTotal ? $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php index 5c3515122b..4e75de27c8 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } @@ -59,7 +60,8 @@ class Get extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB + callable $getLogsDB, + Authorization $authorization, ): void { $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -75,19 +77,20 @@ class Get extends Action $statsDocId = md5('_inf_' . $metric); - $dbForLogs = call_user_func($getLogsDB, $project); - $storageStats = Authorization::skip( - fn () => $dbForLogs->getDocument( + $totalSize = 0; + + try { + $dbForLogs = $getLogsDB($project); + $storageStats = $authorization->skip(fn () => $dbForLogs->getDocument( 'stats', $statsDocId, [Query::select(['value'])] - ) - ); + )); - /** - * The value can be 0 if stats were not aggregated when this request was made! - */ - $totalSize = $storageStats->isEmpty() ? 0 : $storageStats->getAttribute('value', 0); + $totalSize = $storageStats->getAttribute('value', 0); + } catch (\Throwable) { + // Stats may not be available, default to 0 + } $bucket->setAttribute('totalSize', $totalSize); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php index a2c880ce08..601d9b5321 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/XList.php @@ -58,6 +58,7 @@ class XList extends Action ->inject('dbForProject') ->inject('project') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } @@ -68,7 +69,8 @@ class XList extends Action Response $response, Database $dbForProject, Document $project, - callable $getLogsDB + callable $getLogsDB, + Authorization $authorization ) { try { $queries = Query::parseQueries($queries); @@ -117,7 +119,6 @@ class XList extends Action if (!empty($buckets)) { $bucketByStatsId = []; - $dbForLogs = call_user_func($getLogsDB, $project); foreach ($buckets as $bucket) { $metric = str_replace( @@ -134,22 +135,28 @@ class XList extends Action $bucket->setAttribute('totalSize', 0); } - /* @type Document[] $stats */ - $stats = Authorization::skip(function () use ($dbForLogs, $bucketByStatsId) { - $statsIds = array_keys($bucketByStatsId); + try { + $dbForLogs = $getLogsDB($project); - return $dbForLogs->find('stats', [ - Query::equal('$id', $statsIds), - Query::select(['value']), - ]); - }); + /* @var array $stats */ + $stats = $authorization->skip(function () use ($dbForLogs, $bucketByStatsId) { + $statsIds = array_keys($bucketByStatsId); - foreach ($stats as $stat) { - $bucket = $bucketByStatsId[$stat->getId()]; + return $dbForLogs->find('stats', [ + Query::equal('$id', $statsIds), + Query::select(['value']), + ]); + }); - if ($bucket) { - $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); + foreach ($stats as $stat) { + $bucket = $bucketByStatsId[$stat->getId()]; + + if ($bucket) { + $bucket->setAttribute('totalSize', $stat->getAttribute('value', 0)); + } } + } catch (\Throwable) { + // Stats may not be available, default to 0 } } diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php index b816e83f72..a7bda355da 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/Get.php @@ -54,10 +54,11 @@ class Get extends Action ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) + public function action(string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, Authorization $authorization) { $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -75,7 +76,7 @@ class Get extends Action str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php index d29fa7c1b4..44fdd54e8c 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Usage/XList.php @@ -49,10 +49,11 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $range, Response $response, Database $dbForProject) + public function action(string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -63,7 +64,7 @@ class XList extends Action METRIC_FILES_STORAGE, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index f79dece530..5f1bd55788 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -6,32 +6,31 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Documents\User; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; class Action extends UtopiaAction { - protected function getFileAndBucket(Database $dbForProject, string $bucketId, string $fileId): array + protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, string $bucketId, string $fileId): array { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp(Authorization::getRoles()); - $isPrivilegedUser = User::isPrivileged(Authorization::getRoles()); + $isAPIKey = User::isApp($authorization->getRoles()); + $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(Database::PERMISSION_READ); - $valid = $validator->isValid($bucket->getRead()); - if (!$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 3d1f6eef38..6cbaeaa915 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -14,6 +14,7 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -65,23 +66,23 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents): void + public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { /** * @var Document $bucket * @var Document $file */ - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $bucketPermission = $validator->isValid($bucket->getUpdate()); + $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if ($fileSecurity) { - $filePermission = $validator->isValid($file->getUpdate()); + $filePermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); if (!$bucketPermission && !$filePermission) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 8a9301713b..13da92cbc6 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -13,6 +13,7 @@ use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; @@ -57,12 +58,13 @@ class XList extends Action ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) + public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization) { - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 3e35c1c1fa..cc6981fa1b 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -31,6 +31,7 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') + ->inject('authorisation') ->callback($this->action(...)); } @@ -47,8 +48,8 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, + Authorization $authorization ): void { - Authorization::disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); @@ -66,14 +67,14 @@ class Migrate extends Action $count = 0; $total = $dbForPlatform->count('projects') + 1; - $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total, $authorization) { /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); $dbForProject->disableValidation(); try { $migration - ->setProject($project, $dbForProject, $dbForPlatform, $getProjectDB) + ->setProject($project, $dbForProject, $dbForPlatform, $authorization, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -88,7 +89,7 @@ class Migrate extends Action try { $migration - ->setProject($console, $getProjectDB($console), $dbForPlatform, $getProjectDB) + ->setProject($console, $getProjectDB($console), $dbForPlatform, $authorization, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 9698fe9034..19ed3bc099 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -8,7 +8,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; @@ -61,7 +60,7 @@ abstract class ScheduleBase extends Action $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $dbForPlatform->updateDocument('projects', $project->getId(), $project); } } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index b64dd61f86..6d04d2109a 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -8,7 +8,6 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\System\System; /** @@ -61,9 +60,7 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue) { - Authorization::disable(); - Authorization::setDefaultStatus(false); + Console::loop(function () use ($queue, $dbForPlatform) { $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); /** diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 5132687279..33ebd39092 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -21,6 +21,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -58,6 +59,7 @@ class Certificates extends Action ->inject('log') ->inject('certificates') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -72,6 +74,8 @@ class Certificates extends Action * @param Certificate $queueForCertificates * @param Log $log * @param CertificatesAdapter $certificates + * @param array $plan + * @param ValidatorAuthorization $authorization * @return void * @throws Throwable * @throws \Utopia\Database\Exception @@ -87,7 +91,8 @@ class Certificates extends Action Certificate $queueForCertificates, Log $log, CertificatesAdapter $certificates, - array $plan + array $plan, + ValidatorAuthorization $authorization, ): void { $payload = $message->getPayload() ?? []; @@ -106,11 +111,11 @@ class Certificates extends Action switch ($action) { case Certificate::ACTION_DOMAIN_VERIFICATION: - $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $validationDomain); + $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForCertificates, $log, $authorization, $validationDomain); break; case Certificate::ACTION_GENERATION: - $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan, $validationDomain); + $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); break; default: @@ -127,10 +132,12 @@ class Certificates extends Action * @param Realtime $queueForRealtime * @param Certificate $queueForCertificates * @param Log $log + * @param ValidatorAuthorization $authorization * @param string|null $validationDomain * @return void - * @throws Throwable * @throws \Utopia\Database\Exception + * @throws NotFound + * @throws \Utopia\Database\Exception\Query */ private function handleDomainVerificationAction( Domain $domain, @@ -141,12 +148,13 @@ class Certificates extends Action Realtime $queueForRealtime, Certificate $queueForCertificates, Log $log, + ValidatorAuthorization $authorization, ?string $validationDomain = null ): void { // Get rule $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ + ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); @@ -195,15 +203,23 @@ class Certificates extends Action * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents + * @param Webhook $queueForWebhooks * @param Func $queueForFunctions * @param Realtime $queueForRealtime + * @param Log $log * @param CertificatesAdapter $certificates + * @param ValidatorAuthorization $authorization * @param bool $skipRenewCheck * @param array $plan * @param string|null $validationDomain * @return void + * @throws Authorization + * @throws Conflict + * @throws NotFound + * @throws Structure * @throws Throwable * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Query */ private function handleCertificateGenerationAction( Domain $domain, @@ -216,6 +232,7 @@ class Certificates extends Action Realtime $queueForRealtime, Log $log, CertificatesAdapter $certificates, + ValidatorAuthorization $authorization, bool $skipRenewCheck = false, array $plan = [], ?string $validationDomain = null @@ -252,8 +269,8 @@ class Certificates extends Action // Get rule document for domain // TODO: (@Meldiron) Remove after 1.7.x migration $rule = System::getEnv('_APP_RULES_FORMAT') === 'md5' - ? ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) - : ValidatorAuthorization::skip(fn () => $dbForPlatform->findOne('rules', [ + ? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get()))) + : $authorization->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]), Query::limit(1), ])); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 0b2f7c75ae..9687f4f4bb 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -19,12 +19,10 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; -use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -203,7 +201,6 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void - * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -1002,14 +999,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); if ($bucket->isEmpty()) { Console::error('Failed to get bucket for deployment screenshots'); return; } foreach ($screenshotIds as $id) { - $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); + $file = $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 4a564011b2..d047d0925e 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -15,7 +15,6 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; @@ -337,7 +336,6 @@ class Functions extends Action * @param string|null $eventData * @param string|null $executionId * @return void - * @throws Authorization * @throws Structure * @throws \Utopia\Database\Exception * @throws Conflict diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index e1039510f4..6ef2f1899c 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -80,6 +80,7 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -97,6 +98,7 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, + Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -134,7 +136,13 @@ class Migrations extends Action } try { - $this->processMigration($migration, $queueForRealtime, $queueForMails, $platform); + $this->processMigration( + $migration, + $queueForRealtime, + $queueForMails, + $platform, + $authorization + ); } finally { $this->dbForProject = null; $this->dbForPlatform = null; @@ -145,7 +153,7 @@ class Migrations extends Action $this->plan = []; $this->sourceReport = []; - gc_collect_cycles(); + \gc_collect_cycles(); } } @@ -319,6 +327,7 @@ class Migrations extends Action Realtime $queueForRealtime, Mail $queueForMails, array $platform, + Authorization $authorization, ): void { $project = $this->project; @@ -435,14 +444,14 @@ class Migrations extends Action $destination?->success(); $source?->success(); - // todo: Move to CSV hook + // TODO: Move to CSV hook if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization); } } } finally { - $source?->cleanUp(); - $destination?->cleanUp(); + $source?->cleanup(); + $destination?->cleanup(); $transfer = null; $source = null; @@ -457,11 +466,10 @@ class Migrations extends Action * @param Document $project * @param Document $migration * @param Mail $queueForMails + * @param Realtime $queueForRealtime + * @param array $platform + * @param Authorization $authorization * @return void - * @throws AuthorizationException - * @throws Structure - * @throws \Utopia\Database\Exception - * @throws Exception */ protected function handleCSVExportComplete( Document $project, @@ -469,6 +477,7 @@ class Migrations extends Action Mail $queueForMails, Realtime $queueForRealtime, array $platform, + Authorization $authorization, ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -482,7 +491,7 @@ class Migrations extends Action throw new \Exception('User ' . $userInternalId . ' not found'); } - $bucket = Authorization::skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $this->dbForPlatform->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new \Exception('Bucket not found'); } diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index a85b0a897c..cbd22aaee5 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -7,7 +7,6 @@ use Utopia\Auth\Proofs\Token; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; class User extends Document @@ -36,11 +35,11 @@ class User extends Document * * @return array */ - public function getRoles(): array + public function getRoles($authorization): array { $roles = []; - if (!$this->isPrivileged(Authorization::getRoles()) && !$this->isApp(Authorization::getRoles())) { + if (!$this->isPrivileged($authorization->getRoles()) && !$this->isApp($authorization->getRoles())) { if ($this->getId()) { $roles[] = Role::user($this->getId())->toString(); $roles[] = Role::users()->toString(); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index cb449e6ffa..c87279f126 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -214,7 +214,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isAppUser = User::isApp($roles); if ($isAppUser) { @@ -237,4 +237,11 @@ class Request extends UtopiaRequest ksort($params); return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } + + private ?Authorization $authorization = null; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 56fed746d9..6d47d4d150 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -10,7 +10,7 @@ abstract class Filter private array $params; private ?Database $dbForProject; - public function __construct(Database $dbForProject = null, array $params = []) + public function __construct(?Database $dbForProject = null, array $params = []) { $this->params = $params; $this->dbForProject = $dbForProject; diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 69e7da6b7a..e3d5fe2f79 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -7,7 +7,6 @@ use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; class V20 extends Filter { @@ -138,7 +137,7 @@ class V20 extends Filter } try { - $database = Authorization::skip(fn () => $dbForProject->getDocument( + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'databases', $databaseId )); @@ -150,7 +149,7 @@ class V20 extends Filter } try { - $collection = Authorization::skip(fn () => $dbForProject->getDocument( + $collection = $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId )); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 1dfaa1a41f..f2ac486f82 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -483,7 +483,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isPrivilegedUser = DBUser::isPrivileged($roles); $isAppUser = DBUser::isApp($roles); @@ -651,4 +651,11 @@ class Response extends SwooleResponse self::$showSensitive = false; } } + + private ?Authorization $authorization = null; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index 6496aa285a..0c9854160e 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,19 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + + return $this->authorization; + } + public function createCollection(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ @@ -111,8 +124,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -134,7 +147,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +158,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateCollectionId = $data['privateCollectionId']; $databaseId = $data['databaseId']; - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', [ 'content-type' => 'application/json', @@ -222,7 +235,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateDocument['headers']['status-code']); foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index 2f69c037d0..84cb4bce3a 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,19 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + + public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ @@ -111,8 +124,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $publicResponse['headers']['status-code']); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicRows = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -134,7 +147,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +158,8 @@ class DatabasesPermissionsGuestTest extends Scope $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; - $roles = Authorization::getRoles(); - Authorization::cleanRoles(); + $roles = $this->getAuthorization()->getRoles(); + $this->getAuthorization()->cleanRoles(); $publicResponse = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', @@ -222,7 +235,7 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateRow['headers']['status-code']); foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } diff --git a/tests/e2e/Services/Tokens/TokensBase.php b/tests/e2e/Services/Tokens/TokensBase.php index a4461c06c2..ca6feed5fa 100644 --- a/tests/e2e/Services/Tokens/TokensBase.php +++ b/tests/e2e/Services/Tokens/TokensBase.php @@ -94,7 +94,7 @@ trait TokensBase $this->assertEquals(401, $failedPreview['body']['code']); $this->assertEquals(401, $failedPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedPreview['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedPreview['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedPreview['body']['message']); // Extended file preview. Should fail as an anonymous user with no form of any access to the file. $failedCustomPreview = $this->client->call( @@ -113,7 +113,7 @@ trait TokensBase $this->assertEquals(401, $failedCustomPreview['body']['code']); $this->assertEquals(401, $failedCustomPreview['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedCustomPreview['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedCustomPreview['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedCustomPreview['body']['message']); // File view. Should fail as an anonymous user with no form of any access to the file. $failedView = $this->client->call( @@ -124,7 +124,7 @@ trait TokensBase $this->assertEquals(401, $failedView['body']['code']); $this->assertEquals(401, $failedView['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedView['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedView['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedView['body']['message']); // File download. Should fail as an anonymous user with no form of any access to the file. $failedDownload = $this->client->call( @@ -135,7 +135,7 @@ trait TokensBase $this->assertEquals(401, $failedDownload['body']['code']); $this->assertEquals(401, $failedDownload['headers']['status-code']); $this->assertEquals('user_unauthorized', $failedDownload['body']['type']); - $this->assertEquals('The current user is not authorized to perform the requested action.', $failedDownload['body']['message']); + $this->assertEquals('No permissions provided for action \'read\'', $failedDownload['body']['message']); return $data; } diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 42e433568f..7df5b8d1e6 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -7,6 +7,7 @@ use Appwrite\Utopia\Database\Documents\User; use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -33,6 +34,19 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; + + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + public function setUp(): void { /** @@ -65,7 +79,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -89,7 +103,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); diff --git a/tests/unit/Utopia/Database/Documents/UserTest.php b/tests/unit/Utopia/Database/Documents/UserTest.php index 4675e8d73f..d5706e7bec 100644 --- a/tests/unit/Utopia/Database/Documents/UserTest.php +++ b/tests/unit/Utopia/Database/Documents/UserTest.php @@ -14,13 +14,25 @@ use Utopia\Database\Validator\Roles; class UserTest extends TestCase { + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + + $this->authorization = new Authorization(); + return $this->authorization; + } + /** * Reset Roles */ public function tearDown(): void { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); + $this->getAuthorization()->cleanRoles(); + $this->getAuthorization()->addRole(Role::any()->toString()); } public function testSessionVerify(): void @@ -197,7 +209,7 @@ class UserTest extends TestCase '$id' => '' ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -233,7 +245,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -254,21 +266,21 @@ class UserTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles); // Enable single verification type $user['emailVerification'] = true; - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles); $this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles); } public function testPrivilegedUserRoles(): void { - Authorization::setRole(User::ROLE_OWNER); + $this->getAuthorization()->addRole(User::ROLE_OWNER); $user = new User([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -293,8 +305,7 @@ class UserTest extends TestCase ] ] ]); - - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -312,7 +323,7 @@ class UserTest extends TestCase public function testAppUserRoles(): void { - Authorization::setRole(User::ROLE_APPS); + $this->getAuthorization()->addRole(User::ROLE_APPS); $user = new User([ '$id' => ID::custom('123'), 'memberships' => [ @@ -336,7 +347,7 @@ class UserTest extends TestCase ] ]); - $roles = $user->getRoles(); + $roles = $user->getRoles($this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); From 09a337aa1b435221ff6fea5f5945d711c0a47891 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 04:10:57 +1300 Subject: [PATCH 41/52] Fix validators --- .../Databases/Http/Databases/Collections/Create.php | 8 +++++++- .../Http/Databases/Collections/Indexes/Create.php | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 89cc14056a..d0e9539ad4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -186,7 +186,13 @@ class Create extends Action $dbForProject->getAdapter()->getSupportForVectors(), $dbForProject->getAdapter()->getSupportForAttributes(), $dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(), - $dbForProject->getAdapter()->getSupportForIdenticalIndexes() + $dbForProject->getAdapter()->getSupportForIdenticalIndexes(), + $dbForProject->getAdapter()->getSupportForObjectIndexes(), + $dbForProject->getAdapter()->getSupportForTrigramIndex(), + $dbForProject->getAdapter()->getSupportForSpatialAttributes(), + $dbForProject->getAdapter()->getSupportForIndex(), + $dbForProject->getAdapter()->getSupportForUniqueIndex(), + $dbForProject->getAdapter()->getSupportForFulltextIndex(), ); foreach ($collectionIndexes as $indexDoc) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 5b035a8688..7995c19af7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -199,7 +199,13 @@ class Create extends Action $dbForProject->getAdapter()->getSupportForVectors(), $dbForProject->getAdapter()->getSupportForAttributes(), $dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(), - $dbForProject->getAdapter()->getSupportForIdenticalIndexes() + $dbForProject->getAdapter()->getSupportForIdenticalIndexes(), + $dbForProject->getAdapter()->getSupportForObjectIndexes(), + $dbForProject->getAdapter()->getSupportForTrigramIndex(), + $dbForProject->getAdapter()->getSupportForSpatialAttributes(), + $dbForProject->getAdapter()->getSupportForIndex(), + $dbForProject->getAdapter()->getSupportForUniqueIndex(), + $dbForProject->getAdapter()->getSupportForFulltextIndex(), ); if (!$validator->isValid($index)) { From 955e1bcbe97ee2301f2259f306fe6604a3d44284 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 14 Jan 2026 21:29:58 +0530 Subject: [PATCH 42/52] use stable --- app/config/sdks.php | 2 +- composer.lock | 94 +++++++++++++++++++------------------- docs/sdks/cli/CHANGELOG.md | 8 ++++ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/app/config/sdks.php b/app/config/sdks.php index b9d091f24d..15a9c42127 100644 --- a/app/config/sdks.php +++ b/app/config/sdks.php @@ -227,7 +227,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '13.0.0-rc.5', + 'version' => '13.0.0', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/composer.lock b/composer.lock index 8b68b2a1ba..e75065278e 100644 --- a/composer.lock +++ b/composer.lock @@ -3552,23 +3552,23 @@ }, { "name": "utopia-php/audit", - "version": "2.0.2", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "27d66630f528473cb563bbcf362d7d9a711b384e" + "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/27d66630f528473cb563bbcf362d7d9a711b384e", - "reference": "27d66630f528473cb563bbcf362d7d9a711b384e", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/1301ab2607667b9f86456f86895f3e26f8c0c9a7", + "reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7", "shasum": "" }, "require": { "php": ">=8.0", "utopia-php/database": "4.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3595,9 +3595,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/2.0.2" + "source": "https://github.com/utopia-php/audit/tree/2.0.4" }, - "time": "2026-01-07T07:01:25+00:00" + "time": "2026-01-14T07:22:46+00:00" }, { "name": "utopia-php/auth", @@ -3898,16 +3898,16 @@ }, { "name": "utopia-php/database", - "version": "4.4.0", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "783193d5cdc723b3784e8fb399068b17d4228d53" + "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/783193d5cdc723b3784e8fb399068b17d4228d53", - "reference": "783193d5cdc723b3784e8fb399068b17d4228d53", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", + "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", "shasum": "" }, "require": { @@ -3950,9 +3950,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.4.0" + "source": "https://github.com/utopia-php/database/tree/4.5.1" }, - "time": "2026-01-08T04:54:39+00:00" + "time": "2026-01-14T12:07:24+00:00" }, { "name": "utopia-php/detector", @@ -4266,23 +4266,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.36", + "version": "0.33.37", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" + "reference": "30a119d76531d89da9240496940c84fcd9e1758b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", - "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", + "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", + "reference": "30a119d76531d89da9240496940c84fcd9e1758b", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.1.*" + "utopia-php/validators": "0.2.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4308,9 +4308,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.36" + "source": "https://github.com/utopia-php/http/tree/0.33.37" }, - "time": "2026-01-12T07:32:29+00:00" + "time": "2026-01-13T10:10:21+00:00" }, { "name": "utopia-php/image", @@ -4515,16 +4515,16 @@ }, { "name": "utopia-php/migration", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2" + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/4cb7a0e65a36058d153ef5643090414c6525e4a2", - "reference": "4cb7a0e65a36058d153ef5643090414c6525e4a2", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d", + "reference": "52ca4234d8229b68e27e052248734a08784d9d3d", "shasum": "" }, "require": { @@ -4564,9 +4564,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.4.2" + "source": "https://github.com/utopia-php/migration/tree/1.4.3" }, - "time": "2026-01-08T04:46:18+00:00" + "time": "2026-01-13T09:51:08+00:00" }, { "name": "utopia-php/mongo", @@ -5013,22 +5013,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.6", + "version": "0.8.4", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", - "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", + "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.36" + "utopia-php/framework": "0.33.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5058,9 +5058,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.6" + "source": "https://github.com/utopia-php/swoole/tree/0.8.4" }, - "time": "2026-01-12T07:57:35+00:00" + "time": "2025-09-07T09:39:46+00:00" }, { "name": "utopia-php/system", @@ -5170,16 +5170,16 @@ }, { "name": "utopia-php/validators", - "version": "0.1.0", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", - "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", + "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", "shasum": "" }, "require": { @@ -5187,7 +5187,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", + "phpstan/phpstan": "2.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5209,9 +5209,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.1.0" + "source": "https://github.com/utopia-php/validators/tree/0.2.0" }, - "time": "2025-11-18T11:05:46+00:00" + "time": "2026-01-13T09:16:51+00:00" }, { "name": "utopia-php/vcs", @@ -5438,16 +5438,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.8.11", + "version": "1.8.15", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "936404bbcbf4cd692bac102f2912b6c97ac87215" + "reference": "a43e8ba5d539e48f0717df284dbd5dc1fb659d6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/936404bbcbf4cd692bac102f2912b6c97ac87215", - "reference": "936404bbcbf4cd692bac102f2912b6c97ac87215", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a43e8ba5d539e48f0717df284dbd5dc1fb659d6b", + "reference": "a43e8ba5d539e48f0717df284dbd5dc1fb659d6b", "shasum": "" }, "require": { @@ -5483,9 +5483,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.8.11" + "source": "https://github.com/appwrite/sdk-generator/tree/1.8.15" }, - "time": "2026-01-12T08:41:56+00:00" + "time": "2026-01-14T10:42:32+00:00" }, { "name": "doctrine/annotations", @@ -8968,5 +8968,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/docs/sdks/cli/CHANGELOG.md b/docs/sdks/cli/CHANGELOG.md index b55c6e5934..b8dfc56dc5 100644 --- a/docs/sdks/cli/CHANGELOG.md +++ b/docs/sdks/cli/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 13.0.0 + +- Mark release as stable +- Feat: add pull sync on destruction of remote resources (+ confirmation) +- Fix: refine zod schema to check string size +- Validate using zod schema during push cli command +- Maintain order of keys in local config + ## 13.0.0-rc.5 - Fix push all command not working correctly From 71ac9c726449301a5edb377e350e42474a428da4 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 14 Jan 2026 21:37:00 +0530 Subject: [PATCH 43/52] use stable --- composer.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/composer.lock b/composer.lock index 1aba9840eb..11b00ab631 100644 --- a/composer.lock +++ b/composer.lock @@ -3569,7 +3569,7 @@ "php": ">=8.0", "utopia-php/database": "3.*", "utopia-php/fetch": "0.5.*", - "utopia-php/validators": "0.2.*" + "utopia-php/validators": "0.1.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4267,23 +4267,23 @@ }, { "name": "utopia-php/framework", - "version": "0.33.37", + "version": "0.33.36", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "30a119d76531d89da9240496940c84fcd9e1758b" + "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b", - "reference": "30a119d76531d89da9240496940c84fcd9e1758b", + "url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098", + "reference": "fd835ed77e1cdf327067ce4e650cce86304e7098", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/compression": "0.1.*", "utopia-php/telemetry": "0.1.*", - "utopia-php/validators": "0.2.*" + "utopia-php/validators": "0.1.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4309,9 +4309,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.37" + "source": "https://github.com/utopia-php/http/tree/0.33.36" }, - "time": "2026-01-13T10:10:21+00:00" + "time": "2026-01-12T07:32:29+00:00" }, { "name": "utopia-php/image", @@ -5057,22 +5057,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.4", + "version": "0.8.6", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" + "reference": "14b00277c35a258cb263706fd4e05c50368feb4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f", + "reference": "14b00277c35a258cb263706fd4e05c50368feb4f", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.*" + "utopia-php/framework": "0.33.36" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5102,9 +5102,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.4" + "source": "https://github.com/utopia-php/swoole/tree/0.8.6" }, - "time": "2025-09-07T09:39:46+00:00" + "time": "2026-01-12T07:57:35+00:00" }, { "name": "utopia-php/system", @@ -5214,16 +5214,16 @@ }, { "name": "utopia-php/validators", - "version": "0.2.0", + "version": "0.1.0", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "30b6030a5b100fc1dff34506e5053759594b2a20" + "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20", - "reference": "30b6030a5b100fc1dff34506e5053759594b2a20", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080", + "reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080", "shasum": "" }, "require": { @@ -5231,7 +5231,7 @@ }, "require-dev": { "laravel/pint": "1.*", - "phpstan/phpstan": "2.*", + "phpstan/phpstan": "1.*", "phpunit/phpunit": "11.*" }, "type": "library", @@ -5253,9 +5253,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.2.0" + "source": "https://github.com/utopia-php/validators/tree/0.1.0" }, - "time": "2026-01-13T09:16:51+00:00" + "time": "2025-11-18T11:05:46+00:00" }, { "name": "utopia-php/vcs", @@ -9014,5 +9014,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } From c083e1ce741d7200dc51d24d4184cbdb63cae783 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 16:31:37 +1300 Subject: [PATCH 44/52] Throw AppwriteException so handler can unwrap --- src/Appwrite/Platform/Workers/Functions.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index d047d0925e..fbf996319c 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -9,6 +9,7 @@ use Appwrite\Event\Realtime; use Appwrite\Event\StatsUsage; use Appwrite\Event\Webhook; use Appwrite\Utopia\Response\Model\Execution; +use Appwrite\Extend\Exception as AppwriteException; use Exception; use Executor\Executor; use Utopia\CLI\Console; @@ -661,7 +662,11 @@ class Functions extends Action ->trigger(); if (!empty($error)) { - throw new Exception($error, $errorCode); + throw new AppwriteException( + AppwriteException::GENERAL_SERVER_ERROR, + $error ?: 'Function execution failed with no error message', + $errorCode + ); } } } From 7ab3debb10c74e2898c79fdcfb4808f2fabf82ab Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 16:37:09 +1300 Subject: [PATCH 45/52] Format --- src/Appwrite/Platform/Workers/Functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index fbf996319c..e053efa021 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -8,8 +8,8 @@ use Appwrite\Event\Func; use Appwrite\Event\Realtime; use Appwrite\Event\StatsUsage; use Appwrite\Event\Webhook; -use Appwrite\Utopia\Response\Model\Execution; use Appwrite\Extend\Exception as AppwriteException; +use Appwrite\Utopia\Response\Model\Execution; use Exception; use Executor\Executor; use Utopia\CLI\Console; From 7b940e3a177f991c8076491c0e4081244d48c40b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 16:47:19 +1300 Subject: [PATCH 46/52] Increase + parameterise ppolmax reconnect + sleep --- app/init/registers.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/init/registers.php b/app/init/registers.php index 1b58c85aa4..9799c56914 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -324,6 +324,12 @@ $register->set('pools', function () { Config::setParam('pools-' . $key, $config); } + $reconnectAttempts = (int) System::getEnv('_APP_CONNECTIONS_RECONNECT_ATTEMPTS', 5); + $reconnectSleep = (int) System::getEnv('_APP_CONNECTIONS_RECONNECT_SLEEP', 2); + + $group->setReconnectAttempts($reconnectAttempts); + $group->setReconnectSleep($reconnectSleep); + return $group; }); From 728ed57df0ca5f1869d438930d1906c0fb388b7d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 18:43:28 +1300 Subject: [PATCH 47/52] Fix database initialization after utopia-php/database 4.5.2 update The 4.5.2 update removed the automatic USE database statement on init, requiring explicit setDatabase() calls on all database resources. Co-Authored-By: Claude Opus 4.5 --- app/cli.php | 2 ++ app/init/constants.php | 3 +++ app/init/resources.php | 2 ++ app/realtime.php | 1 + app/worker.php | 2 ++ 5 files changed, 10 insertions(+) diff --git a/app/cli.php b/app/cli.php index 7493d10ab3..bca0c75442 100644 --- a/app/cli.php +++ b/app/cli.php @@ -78,6 +78,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) @@ -189,6 +190,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $database = new Database($adapter, $cache); $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') diff --git a/app/init/constants.php b/app/init/constants.php index 0c95c4543b..d51cb6b7af 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -161,6 +161,9 @@ const ACTIVITY_TYPE_GUEST = 'guest'; const MFA_RECENT_DURATION = 1800; // 30 mins +// Database name +const APP_DATABASE = 'appwrite'; + // Database Reconnect const DATABASE_RECONNECT_SLEEP = 2; const DATABASE_RECONNECT_MAX_ATTEMPTS = 10; diff --git a/app/init/resources.php b/app/init/resources.php index 371609da97..afe419f509 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -563,6 +563,7 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authoriz $database = new Database($adapter, $cache); $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) @@ -643,6 +644,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $database = new Database($adapter, $cache); $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') diff --git a/app/realtime.php b/app/realtime.php index 31e6015d92..c041683668 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -66,6 +66,7 @@ if (!function_exists('getConsoleDB')) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, getCache()); $database + ->setDatabase(APP_DATABASE) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', '_console'); diff --git a/app/worker.php b/app/worker.php index d31e63fc8b..5f9d7d88ae 100644 --- a/app/worker.php +++ b/app/worker.php @@ -65,6 +65,7 @@ Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, $dbForPlatform = new Database($adapter, $cache); $dbForPlatform + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setNamespace('_console') ->setDocumentType('users', User::class) @@ -198,6 +199,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authoriza $database = new Database($adapter, $cache); $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') From a0e4e89621549ee592f970b639a2c7b35f3b401e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 18:45:18 +1300 Subject: [PATCH 48/52] Update lock --- composer.lock | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index 6fead373dd..c06922f434 100644 --- a/composer.lock +++ b/composer.lock @@ -3455,24 +3455,25 @@ }, { "name": "utopia-php/abuse", - "version": "1.0.2", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" + "reference": "15cd5dbefa4453e8a2d90649a7078e242966ac3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", - "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/15cd5dbefa4453e8a2d90649a7078e242966ac3f", + "reference": "15cd5dbefa4453e8a2d90649a7078e242966ac3f", "shasum": "" }, "require": { + "appwrite/appwrite": "19.*", "ext-curl": "*", "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "*" + "utopia-php/database": "4.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3500,9 +3501,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/1.0.2" + "source": "https://github.com/utopia-php/abuse/tree/1.2.1" }, - "time": "2025-10-20T07:18:33+00:00" + "time": "2026-01-15T02:09:49+00:00" }, { "name": "utopia-php/analytics", @@ -3898,16 +3899,16 @@ }, { "name": "utopia-php/database", - "version": "4.5.1", + "version": "4.5.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898" + "reference": "8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", - "reference": "7b935bb09aeae8aeff5a28f6f2485cef1cc4d898", + "url": "https://api.github.com/repos/utopia-php/database/zipball/8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23", + "reference": "8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23", "shasum": "" }, "require": { @@ -3950,9 +3951,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.5.1" + "source": "https://github.com/utopia-php/database/tree/4.5.2" }, - "time": "2026-01-14T12:07:24+00:00" + "time": "2026-01-15T04:23:30+00:00" }, { "name": "utopia-php/detector", From b1171c661ea7fe98a21ca1b1613797a0471b532a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 15 Jan 2026 19:08:25 +1300 Subject: [PATCH 49/52] Add setDatabase() to all project database instances This completes the fix for utopia-php/database 4.5.2 which removed the automatic USE database statement. All Database instances that create or query project databases now have explicit setDatabase() calls. Co-Authored-By: Claude Opus 4.5 --- app/cli.php | 1 + app/controllers/api/projects.php | 1 + app/init/resources.php | 2 ++ app/realtime.php | 1 + app/worker.php | 2 ++ 5 files changed, 7 insertions(+) diff --git a/app/cli.php b/app/cli.php index bca0c75442..4b85ba35c6 100644 --- a/app/cli.php +++ b/app/cli.php @@ -169,6 +169,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 74f734a856..b0493ff38f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -227,6 +227,7 @@ App::post('/v1/projects') if (!$sharedTablesV2) { $adapter = new DatabasePool($pools->get($dsn->getHost())); $dbForProject = new Database($adapter, $cache); + $dbForProject->setDatabase(APP_DATABASE); if ($sharedTables) { $dbForProject diff --git a/app/init/resources.php b/app/init/resources.php index afe419f509..a9d46a17be 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -533,6 +533,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $database = new Database($adapter, $cache); $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) @@ -593,6 +594,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $configure = (function (Database $database) use ($project, $dsn, $authorization) { $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) diff --git a/app/realtime.php b/app/realtime.php index c041683668..fcc5329982 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -123,6 +123,7 @@ if (!function_exists('getProjectDB')) { } $database + ->setDatabase(APP_DATABASE) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); diff --git a/app/worker.php b/app/worker.php index 5f9d7d88ae..ba8bf98568 100644 --- a/app/worker.php +++ b/app/worker.php @@ -119,6 +119,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, } $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -180,6 +181,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf } $database + ->setDatabase(APP_DATABASE) ->setAuthorization($authorization) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); From 75696a21bf3699c1b7e2ae5336ef7a0a4c37ee26 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 15 Jan 2026 11:56:19 +0530 Subject: [PATCH 50/52] update: remove excluded keys from descriptions. --- src/Appwrite/SDK/Specification/Format.php | 200 ++++-------------- .../SDK/Specification/Format/OpenAPI3.php | 8 + .../SDK/Specification/Format/Swagger2.php | 8 + 3 files changed, 52 insertions(+), 164 deletions(-) diff --git a/src/Appwrite/SDK/Specification/Format.php b/src/Appwrite/SDK/Specification/Format.php index ed77e568f4..7cb03c8e1b 100644 --- a/src/Appwrite/SDK/Specification/Format.php +++ b/src/Appwrite/SDK/Specification/Format.php @@ -666,171 +666,16 @@ abstract class Format public function getResponseEnumName(string $model, string $param): ?string { - switch ($model) { - case 'attributeString': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeInteger': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeFloat': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeBoolean': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeEmail': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeEnum': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeIp': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeUrl': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeDatetime': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeRelationship': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributePoint': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributeLine': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'attributePolygon': - switch ($param) { - case 'status': - return 'AttributeStatus'; - } - break; - case 'columnString': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnInteger': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnFloat': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnBoolean': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnEmail': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnEnum': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnIp': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnUrl': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnDatetime': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnRelationship': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnPoint': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnLine': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'columnPolygon': - switch ($param) { - case 'status': - return 'ColumnStatus'; - } - break; - case 'healthStatus': - switch ($param) { - case 'status': - return 'HealthCheckStatus'; - } - break; + if ($param !== 'status') { + return null; } - return null; + + return match (true) { + $model === 'healthStatus' => 'HealthCheckStatus', + str_starts_with($model, 'attribute') => 'AttributeStatus', + str_starts_with($model, 'column') => 'ColumnStatus', + default => null, + }; } protected function getNestedModels(Model $model, array &$usedModels): void @@ -852,4 +697,31 @@ abstract class Format } } } + + protected function parseDescription(string $description, array $excludedValues): string + { + if (empty($excludedValues)) { + return $description; + } + + foreach ($excludedValues as $excludedValue) { + // remove from comma-separated list + $description = preg_replace( + '/,\s*' . preg_quote($excludedValue, '/') . '(?=\s*[,.]|$)/', + '', + $description + ); + $description = preg_replace( + '/(?<=:\s|,\s)' . preg_quote($excludedValue, '/') . '\s*,\s*/', + '', + $description + ); + } + + // clean up double commas and extra spaces + $description = preg_replace('/,\s*,/', ',', $description); + $description = preg_replace('/\s+/', ' ', $description); + + return trim($description); + } } diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 27dcf92923..8171a45db4 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -623,6 +623,10 @@ class OpenAPI3 extends Format $node['schema']['items']['enum'] = $enumValues; $node['schema']['items']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); $node['schema']['items']['x-enum-keys'] = $enumKeys; + + if (!empty($excludeKeys)) { + $node['description'] = $this->parseDescription($node['description'], $excludeKeys); + } } if ($validator->getType() === 'integer') { $node['schema']['items']['format'] = $validator->getFormat() ?? 'int32'; @@ -673,6 +677,10 @@ class OpenAPI3 extends Format $node['schema']['enum'] = $enumValues; $node['schema']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); $node['schema']['x-enum-keys'] = $enumKeys; + + if (!empty($excludeKeys)) { + $node['description'] = $this->parseDescription($node['description'], $excludeKeys); + } } if ($validator->getType() === 'integer') { $node['schema']['format'] = $validator->getFormat() ?? 'int32'; diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index de25a57ccc..990c456851 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -607,6 +607,10 @@ class Swagger2 extends Format $node['items']['enum'] = $enumValues; $node['items']['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); $node['items']['x-enum-keys'] = $enumKeys; + + if (!empty($excludeKeys)) { + $node['description'] = $this->parseDescription($node['description'], $excludeKeys); + } } if ($validator->getType() === 'integer') { $node['items']['format'] = $validator->getFormat() ?? 'int32'; @@ -651,6 +655,10 @@ class Swagger2 extends Format $node['enum'] = $enumValues; $node['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); $node['x-enum-keys'] = $enumKeys; + + if (!empty($excludeKeys)) { + $node['description'] = $this->parseDescription($node['description'], $excludeKeys); + } } if ($validator->getType() === 'integer') { $node['format'] = $validator->getFormat() ?? 'int32'; From 206bd63620685792d2f858354e45595eef8a5e21 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 15 Jan 2026 12:04:46 +0530 Subject: [PATCH 51/52] regen: specs. --- app/config/specs/open-api3-latest-client.json | 18 ++++++++++++++++-- app/config/specs/open-api3-latest-console.json | 18 ++++++++++++++++-- app/config/specs/open-api3-latest-server.json | 18 ++++++++++++++++-- app/config/specs/swagger2-latest-client.json | 18 ++++++++++++++++-- app/config/specs/swagger2-latest-console.json | 18 ++++++++++++++++-- app/config/specs/swagger2-latest-server.json | 18 ++++++++++++++++-- 6 files changed, 96 insertions(+), 12 deletions(-) diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 942e83c234..6aef25072a 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -13454,6 +13454,16 @@ "description": "Total number of chunks uploaded", "x-example": 17890, "format": "int32" + }, + "encryption": { + "type": "boolean", + "description": "Whether file contents are encrypted at rest.", + "x-example": true + }, + "compression": { + "type": "string", + "description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" } }, "required": [ @@ -13467,7 +13477,9 @@ "mimeType", "sizeOriginal", "chunksTotal", - "chunksUploaded" + "chunksUploaded", + "encryption", + "compression" ], "example": { "$id": "5e5ea5c16897e", @@ -13482,7 +13494,9 @@ "mimeType": "image\/png", "sizeOriginal": 17890, "chunksTotal": 17890, - "chunksUploaded": 17890 + "chunksUploaded": 17890, + "encryption": true, + "compression": "gzip" } }, "team": { diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index f7cbca76a5..96c074b8ee 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -55191,6 +55191,16 @@ "description": "Total number of chunks uploaded", "x-example": 17890, "format": "int32" + }, + "encryption": { + "type": "boolean", + "description": "Whether file contents are encrypted at rest.", + "x-example": true + }, + "compression": { + "type": "string", + "description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" } }, "required": [ @@ -55204,7 +55214,9 @@ "mimeType", "sizeOriginal", "chunksTotal", - "chunksUploaded" + "chunksUploaded", + "encryption", + "compression" ], "example": { "$id": "5e5ea5c16897e", @@ -55219,7 +55231,9 @@ "mimeType": "image\/png", "sizeOriginal": 17890, "chunksTotal": 17890, - "chunksUploaded": 17890 + "chunksUploaded": 17890, + "encryption": true, + "compression": "gzip" } }, "bucket": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 76e3a2a45c..d86aa78f99 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -43244,6 +43244,16 @@ "description": "Total number of chunks uploaded", "x-example": 17890, "format": "int32" + }, + "encryption": { + "type": "boolean", + "description": "Whether file contents are encrypted at rest.", + "x-example": true + }, + "compression": { + "type": "string", + "description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" } }, "required": [ @@ -43257,7 +43267,9 @@ "mimeType", "sizeOriginal", "chunksTotal", - "chunksUploaded" + "chunksUploaded", + "encryption", + "compression" ], "example": { "$id": "5e5ea5c16897e", @@ -43272,7 +43284,9 @@ "mimeType": "image\/png", "sizeOriginal": 17890, "chunksTotal": 17890, - "chunksUploaded": 17890 + "chunksUploaded": 17890, + "encryption": true, + "compression": "gzip" } }, "bucket": { diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 1d02df124a..0df8d6f382 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -13393,6 +13393,16 @@ "description": "Total number of chunks uploaded", "x-example": 17890, "format": "int32" + }, + "encryption": { + "type": "boolean", + "description": "Whether file contents are encrypted at rest.", + "x-example": true + }, + "compression": { + "type": "string", + "description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" } }, "required": [ @@ -13406,7 +13416,9 @@ "mimeType", "sizeOriginal", "chunksTotal", - "chunksUploaded" + "chunksUploaded", + "encryption", + "compression" ], "example": { "$id": "5e5ea5c16897e", @@ -13421,7 +13433,9 @@ "mimeType": "image\/png", "sizeOriginal": 17890, "chunksTotal": 17890, - "chunksUploaded": 17890 + "chunksUploaded": 17890, + "encryption": true, + "compression": "gzip" } }, "team": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 17064287be..3f2b3d4447 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -55019,6 +55019,16 @@ "description": "Total number of chunks uploaded", "x-example": 17890, "format": "int32" + }, + "encryption": { + "type": "boolean", + "description": "Whether file contents are encrypted at rest.", + "x-example": true + }, + "compression": { + "type": "string", + "description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" } }, "required": [ @@ -55032,7 +55042,9 @@ "mimeType", "sizeOriginal", "chunksTotal", - "chunksUploaded" + "chunksUploaded", + "encryption", + "compression" ], "example": { "$id": "5e5ea5c16897e", @@ -55047,7 +55059,9 @@ "mimeType": "image\/png", "sizeOriginal": 17890, "chunksTotal": 17890, - "chunksUploaded": 17890 + "chunksUploaded": 17890, + "encryption": true, + "compression": "gzip" } }, "bucket": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 6ad3eb4bce..2a452b8658 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -43169,6 +43169,16 @@ "description": "Total number of chunks uploaded", "x-example": 17890, "format": "int32" + }, + "encryption": { + "type": "boolean", + "description": "Whether file contents are encrypted at rest.", + "x-example": true + }, + "compression": { + "type": "string", + "description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" } }, "required": [ @@ -43182,7 +43192,9 @@ "mimeType", "sizeOriginal", "chunksTotal", - "chunksUploaded" + "chunksUploaded", + "encryption", + "compression" ], "example": { "$id": "5e5ea5c16897e", @@ -43197,7 +43209,9 @@ "mimeType": "image\/png", "sizeOriginal": 17890, "chunksTotal": 17890, - "chunksUploaded": 17890 + "chunksUploaded": 17890, + "encryption": true, + "compression": "gzip" } }, "bucket": { From eb07e992250db7dd173b59df29e619c32d61c25c Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 15 Jan 2026 13:48:50 +0530 Subject: [PATCH 52/52] bump: sdk-gen. --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index c06922f434..8b60305dff 100644 --- a/composer.lock +++ b/composer.lock @@ -5482,16 +5482,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.8.15", + "version": "1.8.16", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "a43e8ba5d539e48f0717df284dbd5dc1fb659d6b" + "reference": "e2963002b39f3aa24bd6bf61a78492e182397174" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a43e8ba5d539e48f0717df284dbd5dc1fb659d6b", - "reference": "a43e8ba5d539e48f0717df284dbd5dc1fb659d6b", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/e2963002b39f3aa24bd6bf61a78492e182397174", + "reference": "e2963002b39f3aa24bd6bf61a78492e182397174", "shasum": "" }, "require": { @@ -5527,9 +5527,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.8.15" + "source": "https://github.com/appwrite/sdk-generator/tree/1.8.16" }, - "time": "2026-01-14T10:42:32+00:00" + "time": "2026-01-15T08:16:15+00:00" }, { "name": "doctrine/annotations", @@ -9012,5 +9012,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" }